mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge branch 'release/6.2' into cdecl-6.2
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
|
||||
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
|
||||
#define SWIFTSCAN_VERSION_MAJOR 2
|
||||
#define SWIFTSCAN_VERSION_MINOR 1
|
||||
#define SWIFTSCAN_VERSION_MINOR 2
|
||||
|
||||
SWIFTSCAN_BEGIN_DECLS
|
||||
|
||||
@@ -49,6 +49,9 @@ typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t;
|
||||
/// Opaque container to a link library info.
|
||||
typedef struct swiftscan_link_library_info_s *swiftscan_link_library_info_t;
|
||||
|
||||
/// Opaque container to an import info.
|
||||
typedef struct swiftscan_import_info_s *swiftscan_import_info_t;
|
||||
|
||||
/// Opaque container to a macro dependency.
|
||||
typedef struct swiftscan_macro_dependency_s *swiftscan_macro_dependency_t;
|
||||
|
||||
@@ -76,6 +79,18 @@ typedef struct {
|
||||
size_t count;
|
||||
} swiftscan_link_library_set_t;
|
||||
|
||||
/// Set of details about source imports
|
||||
typedef struct {
|
||||
swiftscan_import_info_t *imports;
|
||||
size_t count;
|
||||
} swiftscan_import_info_set_t;
|
||||
|
||||
/// Set of source location infos
|
||||
typedef struct {
|
||||
swiftscan_source_location_t *source_locations;
|
||||
size_t count;
|
||||
} swiftscan_source_location_set_t;
|
||||
|
||||
/// Set of macro dependency
|
||||
typedef struct {
|
||||
swiftscan_macro_dependency_t *macro_dependencies;
|
||||
@@ -89,6 +104,15 @@ typedef enum {
|
||||
SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK = 3
|
||||
} swiftscan_diagnostic_severity_t;
|
||||
|
||||
// Must maintain consistency with swift::AccessLevel
|
||||
typedef enum {
|
||||
SWIFTSCAN_ACCESS_LEVEL_PRIVATE = 0,
|
||||
SWIFTSCAN_ACCESS_LEVEL_FILEPRIVATE = 1,
|
||||
SWIFTSCAN_ACCESS_LEVEL_INTERNAL = 2,
|
||||
SWIFTSCAN_ACCESS_LEVEL_PACKAGE = 3,
|
||||
SWIFTSCAN_ACCESS_LEVEL_PUBLIC = 4
|
||||
} swiftscan_access_level_t;
|
||||
|
||||
typedef struct {
|
||||
swiftscan_diagnostic_info_t *diagnostics;
|
||||
size_t count;
|
||||
@@ -148,10 +172,23 @@ swiftscan_module_info_get_direct_dependencies(swiftscan_dependency_info_t info);
|
||||
SWIFTSCAN_PUBLIC swiftscan_link_library_set_t *
|
||||
swiftscan_module_info_get_link_libraries(swiftscan_dependency_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_import_info_set_t *
|
||||
swiftscan_module_info_get_imports(swiftscan_dependency_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_module_details_t
|
||||
swiftscan_module_info_get_details(swiftscan_dependency_info_t info);
|
||||
|
||||
//=== Link Library Info Functions ------------------------------------===//
|
||||
//=== Import Details Functions -------------------------------------------===//
|
||||
SWIFTSCAN_PUBLIC swiftscan_source_location_set_t *
|
||||
swiftscan_import_info_get_source_locations(swiftscan_import_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_import_info_get_identifier(swiftscan_import_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_access_level_t
|
||||
swiftscan_import_info_get_access_level(swiftscan_import_info_t info);
|
||||
|
||||
//=== Link Library Info Functions ----------------------------------------===//
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_link_library_info_get_link_name(
|
||||
swiftscan_link_library_info_t info);
|
||||
|
||||
@@ -216,6 +216,9 @@ public:
|
||||
DeclContext *newContext,
|
||||
ClangInheritanceInfo inheritance) = 0;
|
||||
|
||||
/// Returnes the original method if \param decl is a clone from a base class
|
||||
virtual ValueDecl *getOriginalForClonedMember(const ValueDecl *decl) = 0;
|
||||
|
||||
/// Emits diagnostics for any declarations named name
|
||||
/// whose direct declaration context is a TU.
|
||||
virtual void diagnoseTopLevelValue(const DeclName &name) = 0;
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Find the imported module that treats the given nominal type as "preconcurrency", or return `nullptr`
|
||||
/// if there is no such module.
|
||||
ModuleDecl *moduleImportForPreconcurrency(NominalTypeDecl *nominal,
|
||||
const DeclContext *fromDC);
|
||||
|
||||
/// Determinate the appropriate diagnostic behavior to used when emitting
|
||||
/// concurrency diagnostics when referencing the given nominal type from the
|
||||
/// given declaration context.
|
||||
|
||||
@@ -315,12 +315,12 @@ ERROR(missing_never_call_closure,none,
|
||||
(Type))
|
||||
|
||||
ERROR(missing_return_decl,none,
|
||||
"missing return in %1 expected to return %0",
|
||||
(Type, DescriptiveDeclKind))
|
||||
"missing return in %kindonly1 expected to return %0",
|
||||
(Type, const AbstractFunctionDecl *))
|
||||
ERROR(missing_never_call_decl,none,
|
||||
"%1 with uninhabited return type %0 is missing "
|
||||
"%kindonly1 with uninhabited return type %0 is missing "
|
||||
"call to another never-returning function on all paths",
|
||||
(Type, DescriptiveDeclKind))
|
||||
(Type, const AbstractFunctionDecl *))
|
||||
|
||||
NOTE(missing_return_last_expr_note,none,
|
||||
"did you mean to return the last expression?", ())
|
||||
@@ -701,8 +701,9 @@ WARNING(warning_int_to_fp_inexact, none,
|
||||
|
||||
// Flow-isolation diagnostics
|
||||
ERROR(isolated_after_nonisolated, none,
|
||||
"cannot access %1 %2 here in %select{nonisolated initializer|deinitializer}0",
|
||||
(bool, DescriptiveDeclKind, DeclName))
|
||||
"cannot access %kind1 here in "
|
||||
"%select{nonisolated initializer|deinitializer}0",
|
||||
(bool, const ValueDecl *))
|
||||
NOTE(nonisolated_blame, none, "after %1%2 %3, "
|
||||
"only nonisolated properties of 'self' can be accessed from "
|
||||
"%select{this init|a deinit}0", (bool, StringRef, StringRef, DeclName))
|
||||
@@ -840,7 +841,8 @@ ERROR(sil_movechecking_borrowed_parameter_captured_by_closure, none,
|
||||
"parameter",
|
||||
(StringRef))
|
||||
ERROR(sil_movechecking_capture_consumed, none,
|
||||
"noncopyable '%0' cannot be consumed when captured by an escaping closure", (StringRef))
|
||||
"noncopyable '%0' cannot be consumed when captured by an escaping closure or borrowed by a non-Escapable type",
|
||||
(StringRef))
|
||||
ERROR(sil_movechecking_not_reinitialized_before_end_of_function, none,
|
||||
"missing reinitialization of %select{inout parameter|closure capture}1 '%0' "
|
||||
"after consume", (StringRef, bool))
|
||||
@@ -981,23 +983,23 @@ GROUPED_ERROR(regionbasedisolation_type_send_yields_race, SendingRisksDataRace,
|
||||
(Type))
|
||||
NOTE(regionbasedisolation_type_use_after_send, none,
|
||||
"sending value of non-Sendable type %0 to %1 callee risks causing data races between %1 and local %2 uses",
|
||||
(Type, ActorIsolation, ActorIsolation))
|
||||
(Type, StringRef, StringRef))
|
||||
NOTE(regionbasedisolation_type_use_after_send_callee, none,
|
||||
"sending value of non-Sendable type %0 to %1 %2 %3 risks causing data "
|
||||
"races between %1 and local %4 uses",
|
||||
(Type, ActorIsolation, DescriptiveDeclKind, DeclName, ActorIsolation))
|
||||
"sending value of non-Sendable type %0 to %1 %kind2 risks causing data "
|
||||
"races between %1 and local %3 uses",
|
||||
(Type, StringRef, const ValueDecl *, StringRef))
|
||||
|
||||
NOTE(regionbasedisolation_named_info_send_yields_race, none,
|
||||
"sending %1%0 to %2 callee risks causing data races between %2 and local %3 uses",
|
||||
(Identifier, StringRef, ActorIsolation, ActorIsolation))
|
||||
"sending %select{%2 |}0%1 to %3 callee risks causing data races between %3 and local %4 uses",
|
||||
(bool, Identifier, StringRef, StringRef, StringRef))
|
||||
NOTE(regionbasedisolation_named_info_send_yields_race_callee, none,
|
||||
"sending %1%0 to %2 %3 %4 risks causing data races between %2 and local %5 uses",
|
||||
(Identifier, StringRef, ActorIsolation, DescriptiveDeclKind, DeclName, ActorIsolation))
|
||||
"sending %select{%2 |}0%1 to %3 %kind4 risks causing data races between %3 and local %5 uses",
|
||||
(bool, Identifier, StringRef, StringRef, const ValueDecl *, StringRef))
|
||||
|
||||
// Use after send closure.
|
||||
NOTE(regionbasedisolation_type_isolated_capture_yields_race, none,
|
||||
"sending value of non-Sendable type %0 to %1 closure due to closure capture risks causing races in between %1 and %2 uses",
|
||||
(Type, ActorIsolation, ActorIsolation))
|
||||
(Type, StringRef, StringRef))
|
||||
|
||||
// Value captured in async let and reused.
|
||||
NOTE(regionbasedisolation_named_nonisolated_asynclet_name, none,
|
||||
@@ -1008,33 +1010,33 @@ NOTE(regionbasedisolation_named_value_used_after_explicit_sending, none,
|
||||
"%0 used after being passed as a 'sending' parameter; Later uses could race",
|
||||
(Identifier))
|
||||
NOTE(regionbasedisolation_named_isolated_closure_yields_race, none,
|
||||
"%0%1 is captured by a %2 closure. %2 uses in closure may race against later %3 uses",
|
||||
(StringRef, Identifier, ActorIsolation, ActorIsolation))
|
||||
"%select{%1 |}0%2 is captured by a %3 closure. %3 uses in closure may race against later %4 uses",
|
||||
(bool, StringRef, Identifier, StringRef, StringRef))
|
||||
|
||||
NOTE(regionbasedisolation_typed_use_after_sending, none,
|
||||
"Passing value of non-Sendable type %0 as a 'sending' argument risks causing races in between local and caller code",
|
||||
(Type))
|
||||
NOTE(regionbasedisolation_typed_use_after_sending_callee, none,
|
||||
"Passing value of non-Sendable type %0 as a 'sending' argument to %1 %2 risks causing races in between local and caller code",
|
||||
(Type, DescriptiveDeclKind, DeclName))
|
||||
"Passing value of non-Sendable type %0 as a 'sending' argument to %kind1 risks causing races in between local and caller code",
|
||||
(Type, const ValueDecl *))
|
||||
|
||||
//===
|
||||
// Sending Never Sendable Emitter
|
||||
|
||||
NOTE(regionbasedisolation_named_send_never_sendable, none,
|
||||
"sending %1%0 to %2 callee risks causing data races between %2 and %3 uses",
|
||||
(Identifier, StringRef, ActorIsolation, StringRef))
|
||||
"sending %select{%2 |}0%1 to %3 callee risks causing data races between %3 and %4 uses",
|
||||
(bool, Identifier, StringRef, StringRef, StringRef))
|
||||
NOTE(regionbasedisolation_named_send_never_sendable_callee, none,
|
||||
"sending %1%0 to %2 %3 %4 risks causing data races between %2 and %5 uses",
|
||||
(Identifier, StringRef, ActorIsolation, DescriptiveDeclKind, DeclName, StringRef))
|
||||
"sending %select{%2 |}0%1 to %3 %kind4 risks causing data races between %3 and %5 uses",
|
||||
(bool, Identifier, StringRef, StringRef, const ValueDecl *, StringRef))
|
||||
|
||||
NOTE(regionbasedisolation_named_send_into_sending_param, none,
|
||||
"%0%1 is passed as a 'sending' parameter; Uses in callee may race with "
|
||||
"later %0uses",
|
||||
(StringRef, Identifier))
|
||||
"%select{%1 |}0%2 is passed as a 'sending' parameter; Uses in callee may race with "
|
||||
"later %1 uses",
|
||||
(bool, StringRef, Identifier))
|
||||
NOTE(regionbasedisolation_named_nosend_send_into_result, none,
|
||||
"%0%1 cannot be a 'sending' result. %2 uses may race with caller uses",
|
||||
(StringRef, Identifier, StringRef))
|
||||
"%select{%1 |}0%2 cannot be a 'sending' result. %3 uses may race with caller uses",
|
||||
(bool, StringRef, Identifier, StringRef))
|
||||
NOTE(regionbasedisolation_typed_tns_passed_to_sending, none,
|
||||
"Passing %0 value of non-Sendable type %1 as a 'sending' parameter risks "
|
||||
"causing races inbetween %0 uses and uses reachable from the callee",
|
||||
@@ -1050,8 +1052,8 @@ NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_value_
|
||||
"closure captures %0 which is accessible to code in the current task",
|
||||
(DeclName))
|
||||
NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_boxed_value_task_isolated, none,
|
||||
"closure captures reference to mutable %1 %0 which is accessible to code in the current task",
|
||||
(DeclName, DescriptiveDeclKind))
|
||||
"closure captures reference to mutable %kind0 which is accessible to code in the current task",
|
||||
(const ValueDecl *))
|
||||
NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_value_region, none,
|
||||
"closure captures %1 which is accessible to %0 code",
|
||||
(StringRef, DeclName))
|
||||
@@ -1067,18 +1069,22 @@ NOTE(regionbasedisolation_closure_captures_actor, none,
|
||||
(DeclName, StringRef))
|
||||
|
||||
NOTE(regionbasedisolation_typed_tns_passed_to_sending_callee, none,
|
||||
"Passing %0 value of non-Sendable type %1 as a 'sending' parameter to %2 %3 risks causing races inbetween %0 uses and uses reachable from %3",
|
||||
(StringRef, Type, DescriptiveDeclKind, DeclName))
|
||||
"Passing %0 value of non-Sendable type %1 as a 'sending' parameter to %kind2 risks causing races inbetween %0 uses and uses reachable from %2",
|
||||
(StringRef, Type, const ValueDecl *))
|
||||
|
||||
NOTE(regionbasedisolation_named_send_nt_asynclet_capture, none,
|
||||
"sending %1 %0 into async let risks causing data races between nonisolated and %1 uses",
|
||||
(Identifier, StringRef))
|
||||
NOTE(regionbasedisolation_typed_sendneversendable_via_arg, none,
|
||||
"sending %0 value of non-Sendable type %1 to %2 callee risks causing races in between %0 and %2 uses",
|
||||
(StringRef, Type, ActorIsolation))
|
||||
(StringRef, Type, StringRef))
|
||||
NOTE(regionbasedisolation_typed_sendneversendable_via_arg_callee, none,
|
||||
"sending %0 value of non-Sendable type %1 to %2 %3 %4 risks causing races in between %0 and %2 uses",
|
||||
(StringRef, Type, ActorIsolation, DescriptiveDeclKind, DeclName))
|
||||
"sending %0 value of non-Sendable type %1 to %2 %kind3 risks causing races in between %0 and %2 uses",
|
||||
(StringRef, Type, StringRef, const ValueDecl *))
|
||||
|
||||
NOTE(regionbasedisolation_isolated_conformance_introduced, none,
|
||||
"isolated conformance to %kind0 can be introduced here",
|
||||
(const ValueDecl *))
|
||||
|
||||
// Error that is only used when the send non sendable emitter cannot discover any
|
||||
// information to give a better diagnostic.
|
||||
@@ -1092,10 +1098,10 @@ NOTE(regionbasedisolation_inout_sending_must_be_reinitialized, none,
|
||||
"'inout sending' parameter must be reinitialized before function exit with a non-actor isolated value",
|
||||
())
|
||||
ERROR(regionbasedisolation_inout_sending_cannot_be_actor_isolated, none,
|
||||
"'inout sending' parameter %0 cannot be %1at end of function",
|
||||
"'inout sending' parameter %0 cannot be %1 at end of function",
|
||||
(Identifier, StringRef))
|
||||
NOTE(regionbasedisolation_inout_sending_cannot_be_actor_isolated_note, none,
|
||||
"%1%0 risks causing races in between %1uses and caller uses since caller assumes value is not actor isolated",
|
||||
"%1 %0 risks causing races in between %1 uses and caller uses since caller assumes value is not actor isolated",
|
||||
(Identifier, StringRef))
|
||||
|
||||
//===
|
||||
@@ -1120,10 +1126,10 @@ NOTE(regionbasedisolation_out_sending_cannot_be_actor_isolated_note_named, none,
|
||||
// Example: returning main-actor isolated result to a custom-actor isolated context risks causing data races
|
||||
ERROR(rbi_isolation_crossing_result, none,
|
||||
"non-Sendable %0-typed result can not be returned from %1 %kind2 to %3 context",
|
||||
(Type, ActorIsolation, const ValueDecl *, ActorIsolation))
|
||||
(Type, StringRef, const ValueDecl *, StringRef))
|
||||
ERROR(rbi_isolation_crossing_result_no_decl, none,
|
||||
"non-Sendable %0-typed result can not be returned from %1 function to %2 context",
|
||||
(Type, ActorIsolation, ActorIsolation))
|
||||
(Type, StringRef, StringRef))
|
||||
NOTE(rbi_non_sendable_nominal,none,
|
||||
"%kind0 does not conform to the 'Sendable' protocol",
|
||||
(const ValueDecl *))
|
||||
|
||||
@@ -8280,7 +8280,7 @@ ERROR(lifetime_dependence_cannot_use_parsed_borrow_inout, none,
|
||||
ERROR(lifetime_dependence_duplicate_target, none,
|
||||
"invalid duplicate target lifetime dependencies on function", ())
|
||||
ERROR(lifetime_parameter_requires_inout, none,
|
||||
"lifetime-dependent parameter must be 'inout'", (Identifier))
|
||||
"lifetime-dependent parameter '%0' must be 'inout'", (StringRef))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: Lifetime Dependence Requirements
|
||||
@@ -8622,6 +8622,9 @@ GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none,
|
||||
GROUPED_WARNING(isolated_conformance_will_become_nonisolated,IsolatedConformances,none,
|
||||
"conformance of %0 to %1 should be marked 'nonisolated' to retain its behavior with upcoming feature 'InferIsolatedConformances'",
|
||||
(const ValueDecl *, const ValueDecl *))
|
||||
GROUPED_ERROR(isolated_conformance_to_sendable_metatype,IsolatedConformances,none,
|
||||
"cannot form %0 conformance of %1 to SendableMetatype-inheriting %kind2",
|
||||
(ActorIsolation, Type, const ValueDecl *))
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MARK: @_inheritActorContext
|
||||
|
||||
@@ -230,7 +230,7 @@ public:
|
||||
private:
|
||||
bool isOperatorSlow() const;
|
||||
};
|
||||
|
||||
|
||||
class DeclName;
|
||||
class DeclNameRef;
|
||||
class ObjCSelector;
|
||||
|
||||
@@ -156,30 +156,35 @@ struct ScannerImportStatementInfo {
|
||||
uint32_t columnNumber;
|
||||
};
|
||||
|
||||
ScannerImportStatementInfo(std::string importIdentifier, bool isExported)
|
||||
: importLocations(), importIdentifier(importIdentifier),
|
||||
isExported(isExported) {}
|
||||
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
|
||||
AccessLevel accessLevel)
|
||||
: importIdentifier(importIdentifier), importLocations(),
|
||||
isExported(isExported), accessLevel(accessLevel) {}
|
||||
|
||||
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
|
||||
AccessLevel accessLevel,
|
||||
ImportDiagnosticLocationInfo location)
|
||||
: importLocations({location}), importIdentifier(importIdentifier),
|
||||
isExported(isExported) {}
|
||||
: importIdentifier(importIdentifier), importLocations({location}),
|
||||
isExported(isExported), accessLevel(accessLevel) {}
|
||||
|
||||
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
|
||||
AccessLevel accessLevel,
|
||||
SmallVector<ImportDiagnosticLocationInfo, 4> locations)
|
||||
: importLocations(locations), importIdentifier(importIdentifier),
|
||||
isExported(isExported) {}
|
||||
: importIdentifier(importIdentifier), importLocations(locations),
|
||||
isExported(isExported), accessLevel(accessLevel) {}
|
||||
|
||||
void addImportLocation(ImportDiagnosticLocationInfo location) {
|
||||
importLocations.push_back(location);
|
||||
}
|
||||
|
||||
/// Buffer, line & column number of the import statement
|
||||
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
|
||||
/// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar'
|
||||
std::string importIdentifier;
|
||||
/// Buffer, line & column number of the import statement
|
||||
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
|
||||
/// Is this an @_exported import
|
||||
bool isExported;
|
||||
/// Access level of this dependency
|
||||
AccessLevel accessLevel;
|
||||
};
|
||||
|
||||
/// Base class for the variant storage of ModuleDependencyInfo.
|
||||
@@ -942,6 +947,7 @@ public:
|
||||
/// Add a dependency on the given module, if it was not already in the set.
|
||||
void
|
||||
addOptionalModuleImport(StringRef module, bool isExported,
|
||||
AccessLevel accessLevel,
|
||||
llvm::StringSet<> *alreadyAddedModules = nullptr);
|
||||
|
||||
/// Add all of the module imports in the given source
|
||||
@@ -952,12 +958,14 @@ public:
|
||||
|
||||
/// Add a dependency on the given module, if it was not already in the set.
|
||||
void addModuleImport(ImportPath::Module module, bool isExported,
|
||||
AccessLevel accessLevel,
|
||||
llvm::StringSet<> *alreadyAddedModules = nullptr,
|
||||
const SourceManager *sourceManager = nullptr,
|
||||
SourceLoc sourceLocation = SourceLoc());
|
||||
|
||||
/// Add a dependency on the given module, if it was not already in the set.
|
||||
void addModuleImport(StringRef module, bool isExported,
|
||||
AccessLevel accessLevel,
|
||||
llvm::StringSet<> *alreadyAddedModules = nullptr,
|
||||
const SourceManager *sourceManager = nullptr,
|
||||
SourceLoc sourceLocation = SourceLoc());
|
||||
|
||||
@@ -132,7 +132,10 @@
|
||||
#ifndef SWIFT_BASIC_RELATIVEPOINTER_H
|
||||
#define SWIFT_BASIC_RELATIVEPOINTER_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace swift {
|
||||
|
||||
|
||||
@@ -655,6 +655,8 @@ public:
|
||||
ValueDecl *importBaseMemberDecl(ValueDecl *decl, DeclContext *newContext,
|
||||
ClangInheritanceInfo inheritance) override;
|
||||
|
||||
ValueDecl *getOriginalForClonedMember(const ValueDecl *decl) override;
|
||||
|
||||
/// Emits diagnostics for any declarations named name
|
||||
/// whose direct declaration context is a TU.
|
||||
void diagnoseTopLevelValue(const DeclName &name) override;
|
||||
|
||||
@@ -63,6 +63,9 @@ struct swiftscan_dependency_info_s {
|
||||
/// The list of link libraries for this module.
|
||||
swiftscan_link_library_set_t *link_libraries;
|
||||
|
||||
/// The list of source import infos.
|
||||
swiftscan_import_info_set_t *imports;
|
||||
|
||||
/// Specific details of a particular kind of module.
|
||||
swiftscan_module_details_t details;
|
||||
};
|
||||
@@ -74,10 +77,16 @@ struct swiftscan_link_library_info_s {
|
||||
bool forceLoad;
|
||||
};
|
||||
|
||||
struct swiftscan_import_info_s {
|
||||
swiftscan_string_ref_t import_identifier;
|
||||
swiftscan_source_location_set_t *source_locations;
|
||||
swiftscan_access_level_t access_level;
|
||||
};
|
||||
|
||||
struct swiftscan_macro_dependency_s {
|
||||
swiftscan_string_ref_t moduleName;
|
||||
swiftscan_string_ref_t libraryPath;
|
||||
swiftscan_string_ref_t executablePath;
|
||||
swiftscan_string_ref_t module_name;
|
||||
swiftscan_string_ref_t library_path;
|
||||
swiftscan_string_ref_t executable_path;
|
||||
};
|
||||
|
||||
/// Swift modules to be built from a module interface, may have a bridging
|
||||
|
||||
@@ -67,6 +67,9 @@ using IsExportedImport = BCFixed<1>;
|
||||
using LineNumberField = BCFixed<32>;
|
||||
using ColumnNumberField = BCFixed<32>;
|
||||
|
||||
/// Access level of an import
|
||||
using AccessLevelField = BCFixed<8>;
|
||||
|
||||
/// Arrays of various identifiers, distinguished for readability
|
||||
using IdentifierIDArryField = llvm::BCArray<IdentifierIDField>;
|
||||
using ModuleIDArryField = llvm::BCArray<IdentifierIDField>;
|
||||
@@ -192,7 +195,8 @@ using ImportStatementLayout =
|
||||
LineNumberField, // lineNumber
|
||||
ColumnNumberField, // columnNumber
|
||||
IsOptionalImport, // isOptional
|
||||
IsExportedImport // isExported
|
||||
IsExportedImport, // isExported
|
||||
AccessLevelField // accessLevel
|
||||
>;
|
||||
using ImportStatementArrayLayout =
|
||||
BCRecordLayout<IMPORT_STATEMENT_ARRAY_NODE, IdentifierIDArryField>;
|
||||
|
||||
@@ -69,7 +69,7 @@ class CMemoryReader final : public MemoryReader {
|
||||
// that we're likely failing to strip a signed pointer when reading from it.
|
||||
bool hasSignatureBits(RemoteAddress address) {
|
||||
return false;
|
||||
uint64_t addressData = address.getAddressData();
|
||||
uint64_t addressData = address.getRawAddress();
|
||||
return addressData != (addressData & getPtrauthMask());
|
||||
}
|
||||
|
||||
@@ -89,13 +89,12 @@ public:
|
||||
RemoteAddress getSymbolAddress(const std::string &name) override {
|
||||
auto addressData = Impl.getSymbolAddress(Impl.reader_context,
|
||||
name.c_str(), name.size());
|
||||
return RemoteAddress(addressData);
|
||||
return RemoteAddress(addressData, RemoteAddress::DefaultAddressSpace);
|
||||
}
|
||||
|
||||
uint64_t getStringLength(RemoteAddress address) {
|
||||
assert(!hasSignatureBits(address));
|
||||
return Impl.getStringLength(Impl.reader_context,
|
||||
address.getAddressData());
|
||||
return Impl.getStringLength(Impl.reader_context, address.getRawAddress());
|
||||
}
|
||||
|
||||
bool readString(RemoteAddress address, std::string &dest) override {
|
||||
@@ -120,7 +119,7 @@ public:
|
||||
ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
|
||||
assert(!hasSignatureBits(address));
|
||||
void *FreeContext;
|
||||
auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(),
|
||||
auto Ptr = Impl.readBytes(Impl.reader_context, address.getRawAddress(),
|
||||
size, &FreeContext);
|
||||
|
||||
auto Free = Impl.free;
|
||||
@@ -134,8 +133,7 @@ public:
|
||||
return ReadBytesResult(Ptr, freeLambda);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace remote
|
||||
} // namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -288,7 +288,7 @@ public:
|
||||
case ArgStorageKind::Address: {
|
||||
result += '0';
|
||||
result += 'x';
|
||||
uint64_t address = Args[argIndex].Address.getAddressData();
|
||||
uint64_t address = Args[argIndex].Address.getRawAddress();
|
||||
unsigned max = ((address >> 32) != 0 ? 16 : 8);
|
||||
for (unsigned i = 0; i != max; ++i) {
|
||||
result += "0123456789abcdef"[(address >> (max - 1 - i) * 4) & 0xF];
|
||||
|
||||
@@ -105,8 +105,8 @@ class InProcessMemoryReader final : public MemoryReader {
|
||||
return ReadBytesResult(address.getLocalPointer<void>(), [](const void *) {});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace remote
|
||||
} // namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,13 +57,31 @@ public:
|
||||
///
|
||||
/// Returns false if the operation failed.
|
||||
virtual bool readString(RemoteAddress address, std::string &dest) = 0;
|
||||
|
||||
|
||||
/// Attempts to read a remote address from the given address in the remote
|
||||
/// process.
|
||||
///
|
||||
/// Returns false if the operator failed.
|
||||
template <typename IntegerType>
|
||||
bool readRemoteAddress(RemoteAddress address, RemoteAddress &out) {
|
||||
IntegerType buf;
|
||||
if (!readInteger(address, &buf))
|
||||
return false;
|
||||
|
||||
out = RemoteAddress((uint64_t)buf, address.getAddressSpace());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Attempts to read an integer from the given address in the remote
|
||||
/// process.
|
||||
///
|
||||
/// Returns false if the operation failed.
|
||||
template <typename IntegerType>
|
||||
bool readInteger(RemoteAddress address, IntegerType *dest) {
|
||||
static_assert(!std::is_same<RemoteAddress, IntegerType>(),
|
||||
"RemoteAddress cannot be read in directly, use "
|
||||
"readRemoteAddress instead.");
|
||||
|
||||
return readBytes(address, reinterpret_cast<uint8_t*>(dest),
|
||||
sizeof(IntegerType));
|
||||
}
|
||||
@@ -147,7 +165,8 @@ public:
|
||||
virtual RemoteAbsolutePointer resolvePointer(RemoteAddress address,
|
||||
uint64_t readValue) {
|
||||
// Default implementation returns the read value as is.
|
||||
return RemoteAbsolutePointer("", readValue);
|
||||
return RemoteAbsolutePointer(
|
||||
RemoteAddress(readValue, address.getAddressSpace()));
|
||||
}
|
||||
|
||||
/// Performs the inverse operation of \ref resolvePointer.
|
||||
@@ -166,7 +185,7 @@ public:
|
||||
virtual RemoteAbsolutePointer getSymbol(RemoteAddress address) {
|
||||
if (auto symbol = resolvePointerAsSymbol(address))
|
||||
return *symbol;
|
||||
return RemoteAbsolutePointer("", address.getAddressData());
|
||||
return RemoteAbsolutePointer(address);
|
||||
}
|
||||
|
||||
/// Lookup a dynamic symbol name (ie dynamic loader binding) for the given
|
||||
@@ -263,7 +282,7 @@ public:
|
||||
virtual ~MemoryReader() = default;
|
||||
};
|
||||
|
||||
} // end namespace reflection
|
||||
} // end namespace remote
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_REFLECTION_READER_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,85 +18,265 @@
|
||||
#ifndef SWIFT_REMOTE_REMOTEADDRESS_H
|
||||
#define SWIFT_REMOTE_REMOTEADDRESS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include "swift/ABI/MetadataRef.h"
|
||||
#include "swift/Basic/RelativePointer.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace swift {
|
||||
namespace remote {
|
||||
|
||||
/// An abstract address in the remote process's address space.
|
||||
class RemoteAddress {
|
||||
uint64_t Data;
|
||||
public:
|
||||
explicit RemoteAddress(const void *localPtr)
|
||||
: Data(reinterpret_cast<uintptr_t>(localPtr)) {}
|
||||
// The default address space, meaning the remote process address space.
|
||||
static constexpr uint8_t DefaultAddressSpace = 0;
|
||||
|
||||
explicit RemoteAddress(uint64_t addressData) : Data(addressData) {}
|
||||
explicit RemoteAddress(uint64_t addressData, uint8_t addressSpace)
|
||||
: Data(addressData), AddressSpace(addressSpace) {}
|
||||
|
||||
explicit operator bool() const {
|
||||
return Data != 0;
|
||||
explicit RemoteAddress() {}
|
||||
|
||||
explicit operator bool() const { return Data != 0; }
|
||||
|
||||
bool operator==(const RemoteAddress rhs) const {
|
||||
return Data == rhs.Data && AddressSpace == rhs.AddressSpace;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T *getLocalPointer() const {
|
||||
return reinterpret_cast<const T*>(static_cast<uintptr_t>(Data));
|
||||
bool operator!=(const RemoteAddress other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
uint64_t getAddressData() const {
|
||||
return Data;
|
||||
bool inRange(const RemoteAddress &begin, const RemoteAddress &end) const {
|
||||
assert(begin.AddressSpace != end.AddressSpace &&
|
||||
"Unexpected address spaces");
|
||||
if (AddressSpace != begin.AddressSpace)
|
||||
return false;
|
||||
return begin <= *this && *this < end;
|
||||
}
|
||||
|
||||
template<typename IntegerType>
|
||||
RemoteAddress& operator+=(const IntegerType& rhs) {
|
||||
bool operator<(const RemoteAddress rhs) const {
|
||||
assert(AddressSpace == rhs.AddressSpace &&
|
||||
"Comparing remote addresses of different address spaces");
|
||||
return Data < rhs.Data;
|
||||
}
|
||||
|
||||
/// Less than operator to be used for ordering purposes. The default less than
|
||||
/// operator asserts if the address spaces are different, this one takes it
|
||||
/// into account to determine the order of the addresses.
|
||||
bool orderedLessThan(const RemoteAddress rhs) const {
|
||||
if (AddressSpace == rhs.AddressSpace)
|
||||
return Data < rhs.Data;
|
||||
return AddressSpace < rhs.AddressSpace;
|
||||
}
|
||||
|
||||
bool operator<=(const RemoteAddress rhs) const {
|
||||
assert(AddressSpace == rhs.AddressSpace &&
|
||||
"Comparing remote addresses of different address spaces");
|
||||
return Data <= rhs.Data;
|
||||
}
|
||||
|
||||
/// Less than or equal operator to be used for ordering purposes. The default
|
||||
/// less than or equal operator asserts if the address spaces are different,
|
||||
/// this one takes it into account to determine the order of the addresses.
|
||||
bool orderedLessThanOrEqual(const RemoteAddress rhs) const {
|
||||
if (AddressSpace == rhs.AddressSpace)
|
||||
return Data <= rhs.Data;
|
||||
return AddressSpace <= rhs.AddressSpace;
|
||||
}
|
||||
|
||||
bool operator>(const RemoteAddress &rhs) const {
|
||||
assert(AddressSpace == rhs.AddressSpace &&
|
||||
"Comparing remote addresses of different address spaces");
|
||||
return Data > rhs.Data;
|
||||
}
|
||||
|
||||
bool operator>=(const RemoteAddress &rhs) const { return Data >= rhs.Data; }
|
||||
|
||||
template <typename IntegerType>
|
||||
RemoteAddress &operator+=(const IntegerType rhs) {
|
||||
Data += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename IntegerType>
|
||||
friend RemoteAddress operator+(RemoteAddress lhs,
|
||||
const IntegerType& rhs) {
|
||||
return lhs += rhs;
|
||||
template <typename IntegerType>
|
||||
RemoteAddress operator+(const IntegerType &rhs) const {
|
||||
return RemoteAddress(Data + rhs, getAddressSpace());
|
||||
}
|
||||
|
||||
template <typename IntegerType>
|
||||
RemoteAddress operator-(const IntegerType &rhs) const {
|
||||
return RemoteAddress(Data - rhs, getAddressSpace());
|
||||
}
|
||||
|
||||
RemoteAddress operator-(const RemoteAddress &rhs) const {
|
||||
if (AddressSpace != rhs.AddressSpace)
|
||||
return RemoteAddress();
|
||||
return RemoteAddress(Data - rhs.Data, getAddressSpace());
|
||||
}
|
||||
|
||||
template <typename IntegerType>
|
||||
RemoteAddress operator^(const IntegerType &rhs) const {
|
||||
return RemoteAddress(Data ^ rhs, getAddressSpace());
|
||||
}
|
||||
|
||||
template <class IntegerType>
|
||||
RemoteAddress operator&(IntegerType other) const {
|
||||
return RemoteAddress(Data & other, getAddressSpace());
|
||||
}
|
||||
|
||||
template <typename IntegerType>
|
||||
RemoteAddress &operator&=(const IntegerType rhs) {
|
||||
Data &= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IntegerType>
|
||||
RemoteAddress &operator|=(const IntegerType rhs) {
|
||||
Data |= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IntegerType>
|
||||
IntegerType operator>>(const IntegerType rhs) const {
|
||||
return (IntegerType)Data >> rhs;
|
||||
}
|
||||
|
||||
uint64_t getRawAddress() const { return Data; }
|
||||
|
||||
uint8_t getAddressSpace() const { return AddressSpace; }
|
||||
|
||||
template <class IntegerType>
|
||||
RemoteAddress applyRelativeOffset(IntegerType offset) const {
|
||||
auto atOffset = detail::applyRelativeOffset((const char *)Data, offset);
|
||||
return RemoteAddress(atOffset, getAddressSpace());
|
||||
}
|
||||
|
||||
template <typename T, bool Nullable, typename Offset>
|
||||
RemoteAddress getRelative(
|
||||
const RelativeDirectPointer<T, Nullable, Offset> *relative) const {
|
||||
auto ptr = relative->getRelative((void *)Data);
|
||||
return RemoteAddress((uint64_t)ptr, getAddressSpace());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T *getLocalPointer() const {
|
||||
return reinterpret_cast<const T *>(static_cast<uintptr_t>(Data));
|
||||
}
|
||||
|
||||
std::string getDescription() const {
|
||||
std::stringstream sstream;
|
||||
// FIXME: this should print the address space too, but because Node can't
|
||||
// carry the address space yet, comparing the strings produced by this type
|
||||
// and a Node that carries an address would produce incorrect results.
|
||||
// Revisit this once Node carries the address space.
|
||||
sstream << std::hex << Data;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
friend llvm::hash_code hash_value(const RemoteAddress &address) {
|
||||
using llvm::hash_value;
|
||||
return hash_value(address.Data);
|
||||
}
|
||||
|
||||
friend struct std::hash<swift::remote::RemoteAddress>;
|
||||
|
||||
private:
|
||||
uint64_t Data = 0;
|
||||
uint8_t AddressSpace = 0;
|
||||
};
|
||||
|
||||
/// A symbolic relocated absolute pointer value.
|
||||
class RemoteAbsolutePointer {
|
||||
/// The symbol name that the pointer refers to. Empty if the value is absolute.
|
||||
/// The symbol name that the pointer refers to. Empty if only an absolute
|
||||
/// address is available.
|
||||
std::string Symbol;
|
||||
/// The offset from the symbol, or the resolved remote address if \c Symbol is empty.
|
||||
int64_t Offset;
|
||||
/// The offset from the symbol.
|
||||
int64_t Offset = 0;
|
||||
/// The resolved remote address.
|
||||
RemoteAddress Address = RemoteAddress();
|
||||
|
||||
public:
|
||||
RemoteAbsolutePointer()
|
||||
: Symbol(), Offset(0)
|
||||
{}
|
||||
|
||||
RemoteAbsolutePointer(std::nullptr_t)
|
||||
: RemoteAbsolutePointer()
|
||||
{}
|
||||
|
||||
RemoteAbsolutePointer(llvm::StringRef Symbol, int64_t Offset)
|
||||
: Symbol(Symbol), Offset(Offset)
|
||||
{}
|
||||
|
||||
bool isResolved() const { return Symbol.empty(); }
|
||||
RemoteAbsolutePointer() = default;
|
||||
RemoteAbsolutePointer(std::nullptr_t) : RemoteAbsolutePointer() {}
|
||||
|
||||
RemoteAbsolutePointer(llvm::StringRef Symbol, int64_t Offset,
|
||||
RemoteAddress Address)
|
||||
: Symbol(Symbol), Offset(Offset), Address(Address) {}
|
||||
RemoteAbsolutePointer(RemoteAddress Address) : Address(Address) {}
|
||||
|
||||
llvm::StringRef getSymbol() const { return Symbol; }
|
||||
int64_t getOffset() const { return Offset; }
|
||||
|
||||
RemoteAddress getResolvedAddress() const {
|
||||
assert(isResolved());
|
||||
return RemoteAddress(Offset);
|
||||
}
|
||||
|
||||
|
||||
RemoteAddress getResolvedAddress() const { return Address; }
|
||||
|
||||
explicit operator bool() const {
|
||||
return Offset != 0 || !Symbol.empty();
|
||||
return Address || !Symbol.empty();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Runtime>
|
||||
class RemoteTargetProtocolDescriptorRef {
|
||||
TargetProtocolDescriptorRef<Runtime> ProtocolRef;
|
||||
RemoteAddress address;
|
||||
|
||||
public:
|
||||
RemoteTargetProtocolDescriptorRef(RemoteAddress address)
|
||||
: ProtocolRef(address.getRawAddress()), address(address) {}
|
||||
|
||||
bool isObjC() const { return ProtocolRef.isObjC(); }
|
||||
|
||||
RemoteAddress getObjCProtocol() const {
|
||||
auto pointer = ProtocolRef.getObjCProtocol();
|
||||
return RemoteAddress(pointer, address.getAddressSpace());
|
||||
}
|
||||
|
||||
RemoteAddress getSwiftProtocol() const {
|
||||
auto pointer = ProtocolRef.getSwiftProtocol();
|
||||
return RemoteAddress(pointer, address.getAddressSpace());
|
||||
}
|
||||
};
|
||||
} // end namespace remote
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_REMOTE_REMOTEADDRESS_H
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<swift::remote::RemoteAddress> {
|
||||
size_t operator()(const swift::remote::RemoteAddress &address) const {
|
||||
return llvm::hash_combine(address.Data, address.AddressSpace);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace llvm {
|
||||
template <>
|
||||
struct DenseMapInfo<swift::remote::RemoteAddress> {
|
||||
static swift::remote::RemoteAddress getEmptyKey() {
|
||||
return swift::remote::RemoteAddress(DenseMapInfo<uint64_t>::getEmptyKey(),
|
||||
0);
|
||||
}
|
||||
|
||||
static swift::remote::RemoteAddress getTombstoneKey() {
|
||||
return swift::remote::RemoteAddress(
|
||||
DenseMapInfo<uint64_t>::getTombstoneKey(), 0);
|
||||
}
|
||||
|
||||
static unsigned getHashValue(swift::remote::RemoteAddress address) {
|
||||
return std::hash<swift::remote::RemoteAddress>()(address);
|
||||
}
|
||||
static bool isEqual(swift::remote::RemoteAddress lhs,
|
||||
swift::remote::RemoteAddress rhs) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // SWIFT_REMOTE_REMOTEADDRESS_H
|
||||
|
||||
@@ -123,8 +123,7 @@ class ReflectionContext
|
||||
using super::readMetadata;
|
||||
using super::readObjCClassName;
|
||||
using super::readResolvedPointerValue;
|
||||
llvm::DenseMap<std::pair<typename super::StoredPointer,
|
||||
remote::TypeInfoProvider::IdType>,
|
||||
llvm::DenseMap<std::pair<RemoteAddress, remote::TypeInfoProvider::IdType>,
|
||||
const RecordTypeInfo *>
|
||||
Cache;
|
||||
|
||||
@@ -256,17 +255,15 @@ public:
|
||||
|
||||
// The layout of the executable is such that the commands immediately follow
|
||||
// the header.
|
||||
auto CmdStartAddress =
|
||||
RemoteAddress(ImageStart.getAddressData() + sizeof(typename T::Header));
|
||||
auto CmdStartAddress = ImageStart + sizeof(typename T::Header);
|
||||
uint32_t SegmentCmdHdrSize = sizeof(typename T::SegmentCmd);
|
||||
uint64_t Offset = 0;
|
||||
|
||||
// Find the __TEXT segment.
|
||||
typename T::SegmentCmd *TextCommand = nullptr;
|
||||
for (unsigned I = 0; I < NumCommands; ++I) {
|
||||
auto CmdBuf = this->getReader().readBytes(
|
||||
RemoteAddress(CmdStartAddress.getAddressData() + Offset),
|
||||
SegmentCmdHdrSize);
|
||||
auto CmdBuf = this->getReader().readBytes(CmdStartAddress + Offset,
|
||||
SegmentCmdHdrSize);
|
||||
if (!CmdBuf)
|
||||
return {};
|
||||
auto CmdHdr = reinterpret_cast<typename T::SegmentCmd *>(CmdBuf.get());
|
||||
@@ -283,26 +280,24 @@ public:
|
||||
return {};
|
||||
|
||||
// Find the load command offset.
|
||||
auto loadCmdOffset = ImageStart.getAddressData() + Offset + sizeof(typename T::Header);
|
||||
auto loadCmdOffset = ImageStart + Offset + sizeof(typename T::Header);
|
||||
|
||||
// Read the load command.
|
||||
auto LoadCmdAddress = reinterpret_cast<const char *>(loadCmdOffset);
|
||||
auto LoadCmdBuf = this->getReader().readBytes(
|
||||
RemoteAddress(LoadCmdAddress), sizeof(typename T::SegmentCmd));
|
||||
loadCmdOffset, sizeof(typename T::SegmentCmd));
|
||||
if (!LoadCmdBuf)
|
||||
return {};
|
||||
auto LoadCmd = reinterpret_cast<typename T::SegmentCmd *>(LoadCmdBuf.get());
|
||||
|
||||
// The sections start immediately after the load command.
|
||||
unsigned NumSect = LoadCmd->nsects;
|
||||
auto SectAddress = reinterpret_cast<const char *>(loadCmdOffset) +
|
||||
sizeof(typename T::SegmentCmd);
|
||||
auto SectAddress = loadCmdOffset + sizeof(typename T::SegmentCmd);
|
||||
auto Sections = this->getReader().readBytes(
|
||||
RemoteAddress(SectAddress), NumSect * sizeof(typename T::Section));
|
||||
SectAddress, NumSect * sizeof(typename T::Section));
|
||||
if (!Sections)
|
||||
return {};
|
||||
|
||||
auto Slide = ImageStart.getAddressData() - TextCommand->vmaddr;
|
||||
auto Slide = ImageStart - TextCommand->vmaddr;
|
||||
auto SectionsBuf = reinterpret_cast<const char *>(Sections.get());
|
||||
|
||||
auto findMachOSectionByName = [&](llvm::StringRef Name)
|
||||
@@ -313,9 +308,9 @@ public:
|
||||
if (strncmp(S->sectname, Name.data(), sizeof(S->sectname)) != 0)
|
||||
continue;
|
||||
|
||||
auto RemoteSecStart = S->addr + Slide;
|
||||
auto RemoteSecStart = Slide + S->addr;
|
||||
auto LocalSectBuf =
|
||||
this->getReader().readBytes(RemoteAddress(RemoteSecStart), S->size);
|
||||
this->getReader().readBytes(RemoteSecStart, S->size);
|
||||
if (!LocalSectBuf)
|
||||
return {nullptr, 0};
|
||||
|
||||
@@ -368,14 +363,12 @@ public:
|
||||
|
||||
auto TextSegmentStart = Slide + TextCommand->vmaddr;
|
||||
auto TextSegmentEnd = TextSegmentStart + TextCommand->vmsize;
|
||||
textRanges.push_back(std::make_tuple(RemoteAddress(TextSegmentStart),
|
||||
RemoteAddress(TextSegmentEnd)));
|
||||
textRanges.push_back(std::make_tuple(TextSegmentStart, TextSegmentEnd));
|
||||
|
||||
// Find the __DATA segments.
|
||||
for (unsigned I = 0; I < NumCommands; ++I) {
|
||||
auto CmdBuf = this->getReader().readBytes(
|
||||
RemoteAddress(CmdStartAddress.getAddressData() + Offset),
|
||||
SegmentCmdHdrSize);
|
||||
auto CmdBuf = this->getReader().readBytes(CmdStartAddress + Offset,
|
||||
SegmentCmdHdrSize);
|
||||
if (!CmdBuf)
|
||||
return {};
|
||||
auto CmdHdr = reinterpret_cast<typename T::SegmentCmd *>(CmdBuf.get());
|
||||
@@ -384,10 +377,9 @@ public:
|
||||
strncmp(CmdHdr->segname, "__AUTH", 6) == 0) {
|
||||
auto DataSegmentStart = Slide + CmdHdr->vmaddr;
|
||||
auto DataSegmentEnd = DataSegmentStart + CmdHdr->vmsize;
|
||||
assert(DataSegmentStart > ImageStart.getAddressData() &&
|
||||
assert(DataSegmentStart > ImageStart &&
|
||||
"invalid range for __DATA/__AUTH");
|
||||
dataRanges.push_back(std::make_tuple(RemoteAddress(DataSegmentStart),
|
||||
RemoteAddress(DataSegmentEnd)));
|
||||
dataRanges.push_back(std::make_tuple(DataSegmentStart, DataSegmentEnd));
|
||||
}
|
||||
Offset += CmdHdr->cmdsize;
|
||||
}
|
||||
@@ -407,12 +399,11 @@ public:
|
||||
return {};
|
||||
auto DOSHdr =
|
||||
reinterpret_cast<const llvm::object::dos_header *>(DOSHdrBuf.get());
|
||||
auto COFFFileHdrAddr = ImageStart.getAddressData() +
|
||||
DOSHdr->AddressOfNewExeHeader +
|
||||
auto COFFFileHdrAddr = ImageStart + DOSHdr->AddressOfNewExeHeader +
|
||||
sizeof(llvm::COFF::PEMagic);
|
||||
|
||||
auto COFFFileHdrBuf = this->getReader().readBytes(
|
||||
RemoteAddress(COFFFileHdrAddr), sizeof(llvm::object::coff_file_header));
|
||||
COFFFileHdrAddr, sizeof(llvm::object::coff_file_header));
|
||||
if (!COFFFileHdrBuf)
|
||||
return {};
|
||||
auto COFFFileHdr = reinterpret_cast<const llvm::object::coff_file_header *>(
|
||||
@@ -422,7 +413,7 @@ public:
|
||||
sizeof(llvm::object::coff_file_header) +
|
||||
COFFFileHdr->SizeOfOptionalHeader;
|
||||
auto SectionTableBuf = this->getReader().readBytes(
|
||||
RemoteAddress(SectionTableAddr),
|
||||
SectionTableAddr,
|
||||
sizeof(llvm::object::coff_section) * COFFFileHdr->NumberOfSections);
|
||||
if (!SectionTableBuf)
|
||||
return {};
|
||||
@@ -440,9 +431,8 @@ public:
|
||||
: llvm::StringRef(COFFSec->Name, llvm::COFF::NameSize);
|
||||
if (SectionName != Name)
|
||||
continue;
|
||||
auto Addr = ImageStart.getAddressData() + COFFSec->VirtualAddress;
|
||||
auto Buf = this->getReader().readBytes(RemoteAddress(Addr),
|
||||
COFFSec->VirtualSize);
|
||||
auto Addr = ImageStart + COFFSec->VirtualAddress;
|
||||
auto Buf = this->getReader().readBytes(Addr, COFFSec->VirtualSize);
|
||||
if (!Buf)
|
||||
return {nullptr, 0};
|
||||
auto BufStart = Buf.get();
|
||||
@@ -512,10 +502,9 @@ public:
|
||||
|
||||
auto DOSHdr = reinterpret_cast<const llvm::object::dos_header *>(Buf.get());
|
||||
|
||||
auto PEHeaderAddress =
|
||||
ImageStart.getAddressData() + DOSHdr->AddressOfNewExeHeader;
|
||||
auto PEHeaderAddress = ImageStart + DOSHdr->AddressOfNewExeHeader;
|
||||
|
||||
Buf = this->getReader().readBytes(RemoteAddress(PEHeaderAddress),
|
||||
Buf = this->getReader().readBytes(PEHeaderAddress,
|
||||
sizeof(llvm::COFF::PEMagic));
|
||||
if (!Buf)
|
||||
return {};
|
||||
@@ -635,6 +624,9 @@ public:
|
||||
return {nullptr, 0};
|
||||
// Now for all the sections, find their name.
|
||||
for (const typename T::Section *Hdr : SecHdrVec) {
|
||||
// Skip unused headers
|
||||
if (Hdr->sh_type == llvm::ELF::SHT_NULL)
|
||||
continue;
|
||||
uint32_t Offset = Hdr->sh_name;
|
||||
const char *Start = (const char *)StrTab + Offset;
|
||||
uint64_t StringSize = strnlen(Start, StrTabSize - Offset);
|
||||
@@ -647,8 +639,7 @@ public:
|
||||
continue;
|
||||
if (Retained != bool(Hdr->sh_flags & llvm::ELF::SHF_GNU_RETAIN))
|
||||
continue;
|
||||
RemoteAddress SecStart =
|
||||
RemoteAddress(ImageStart.getAddressData() + Hdr->sh_addr);
|
||||
RemoteAddress SecStart = ImageStart + Hdr->sh_addr;
|
||||
auto SecSize = Hdr->sh_size;
|
||||
MemoryReader::ReadBytesResult SecBuf;
|
||||
if (FileBuffer.has_value()) {
|
||||
@@ -670,8 +661,7 @@ public:
|
||||
}
|
||||
if (!SecBuf)
|
||||
return {nullptr, 0};
|
||||
auto SecContents =
|
||||
RemoteRef<void>(SecStart.getAddressData(), SecBuf.get());
|
||||
auto SecContents = RemoteRef<void>(SecStart, SecBuf.get());
|
||||
savedBuffers.push_back(std::move(SecBuf));
|
||||
return {SecContents, SecSize};
|
||||
}
|
||||
@@ -904,10 +894,10 @@ public:
|
||||
}
|
||||
|
||||
bool ownsObject(RemoteAddress ObjectAddress) {
|
||||
auto MetadataAddress = readMetadataFromInstance(ObjectAddress.getAddressData());
|
||||
auto MetadataAddress = readMetadataFromInstance(ObjectAddress);
|
||||
if (!MetadataAddress)
|
||||
return true;
|
||||
return ownsAddress(RemoteAddress(*MetadataAddress));
|
||||
return ownsAddress(*MetadataAddress);
|
||||
}
|
||||
|
||||
/// Returns true if the address falls within the given address ranges.
|
||||
@@ -917,8 +907,7 @@ public:
|
||||
for (auto Range : ranges) {
|
||||
auto Start = std::get<0>(Range);
|
||||
auto End = std::get<1>(Range);
|
||||
if (Start.getAddressData() <= Address.getAddressData()
|
||||
&& Address.getAddressData() < End.getAddressData())
|
||||
if (Address.inRange(Start, End))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -940,10 +929,10 @@ public:
|
||||
// This is usually called on a Metadata address which might have been
|
||||
// on the heap. Try reading it and looking up its type context descriptor
|
||||
// instead.
|
||||
if (auto Metadata = readMetadata(Address.getAddressData()))
|
||||
if (auto Metadata = readMetadata(Address))
|
||||
if (auto DescriptorAddress =
|
||||
super::readAddressOfNominalTypeDescriptor(Metadata, true))
|
||||
if (ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
|
||||
if (ownsAddress(DescriptorAddress, textRanges))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -951,17 +940,18 @@ public:
|
||||
|
||||
/// Returns the address of the nominal type descriptor given a metadata
|
||||
/// address.
|
||||
StoredPointer nominalTypeDescriptorFromMetadata(StoredPointer MetadataAddress) {
|
||||
RemoteAddress
|
||||
nominalTypeDescriptorFromMetadata(RemoteAddress MetadataAddress) {
|
||||
auto Metadata = readMetadata(MetadataAddress);
|
||||
if (!Metadata)
|
||||
return 0;
|
||||
return RemoteAddress();
|
||||
return super::readAddressOfNominalTypeDescriptor(Metadata, true);
|
||||
}
|
||||
|
||||
/// Return a description of the layout of a class instance with the given
|
||||
/// metadata as its isa pointer.
|
||||
const RecordTypeInfo *
|
||||
getMetadataTypeInfo(StoredPointer MetadataAddress,
|
||||
getMetadataTypeInfo(RemoteAddress MetadataAddress,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
// See if we cached the layout already
|
||||
auto ExternalTypeInfoId = ExternalTypeInfo ? ExternalTypeInfo->getId() : 0;
|
||||
@@ -1002,7 +992,7 @@ public:
|
||||
/// Return a description of the layout of a class instance with the given
|
||||
/// metadata as its isa pointer.
|
||||
const TypeInfo *
|
||||
getInstanceTypeInfo(StoredPointer ObjectAddress,
|
||||
getInstanceTypeInfo(RemoteAddress ObjectAddress,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
auto MetadataAddress = readMetadataFromInstance(ObjectAddress);
|
||||
if (!MetadataAddress)
|
||||
@@ -1020,7 +1010,7 @@ public:
|
||||
auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress);
|
||||
if (!CDAddr)
|
||||
return nullptr;
|
||||
if (!CDAddr->isResolved())
|
||||
if (!CDAddr->getResolvedAddress())
|
||||
return nullptr;
|
||||
|
||||
// FIXME: Non-generic SIL boxes also use the HeapLocalVariable metadata
|
||||
@@ -1029,8 +1019,7 @@ public:
|
||||
//
|
||||
// Non-generic SIL boxes share metadata among types with compatible
|
||||
// layout, but we need some way to get an outgoing pointer map for them.
|
||||
auto CD = getBuilder().getCaptureDescriptor(
|
||||
CDAddr->getResolvedAddress().getAddressData());
|
||||
auto CD = getBuilder().getCaptureDescriptor(CDAddr->getResolvedAddress());
|
||||
if (CD == nullptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -1045,8 +1034,9 @@ public:
|
||||
if (auto Meta = readMetadata(*MetadataAddress)) {
|
||||
if (auto *GenericHeapMeta = cast<TargetGenericBoxHeapMetadata<Runtime>>(
|
||||
Meta.getLocalBuffer())) {
|
||||
auto MetadataAddress = GenericHeapMeta->BoxedType;
|
||||
auto TR = readTypeFromMetadata(MetadataAddress);
|
||||
auto BoxedTypeAddress = RemoteAddress(
|
||||
GenericHeapMeta->BoxedType, ObjectAddress.getAddressSpace());
|
||||
auto TR = readTypeFromMetadata(BoxedTypeAddress);
|
||||
return getTypeInfo(TR, ExternalTypeInfo);
|
||||
}
|
||||
}
|
||||
@@ -1064,8 +1054,7 @@ public:
|
||||
|
||||
std::optional<std::pair<const TypeRef *, RemoteAddress>>
|
||||
getDynamicTypeAndAddressClassExistential(RemoteAddress ExistentialAddress) {
|
||||
auto PointerValue =
|
||||
readResolvedPointerValue(ExistentialAddress.getAddressData());
|
||||
auto PointerValue = readResolvedPointerValue(ExistentialAddress);
|
||||
if (!PointerValue)
|
||||
return {};
|
||||
auto Result = readMetadataFromInstance(*PointerValue);
|
||||
@@ -1074,7 +1063,7 @@ public:
|
||||
auto TypeResult = readTypeFromMetadata(Result.value());
|
||||
if (!TypeResult)
|
||||
return {};
|
||||
return {{std::move(TypeResult), RemoteAddress(*PointerValue)}};
|
||||
return {{std::move(TypeResult), *PointerValue}};
|
||||
}
|
||||
|
||||
std::optional<std::pair<const TypeRef *, RemoteAddress>>
|
||||
@@ -1084,8 +1073,7 @@ public:
|
||||
if (!Result)
|
||||
return {};
|
||||
|
||||
auto TypeResult =
|
||||
readTypeFromMetadata(Result->MetadataAddress.getAddressData());
|
||||
auto TypeResult = readTypeFromMetadata(Result->MetadataAddress);
|
||||
if (!TypeResult)
|
||||
return {};
|
||||
|
||||
@@ -1101,8 +1089,7 @@ public:
|
||||
if (!Result)
|
||||
return {};
|
||||
|
||||
auto TypeResult =
|
||||
readTypeFromMetadata(Result->MetadataAddress.getAddressData());
|
||||
auto TypeResult = readTypeFromMetadata(Result->MetadataAddress);
|
||||
if (!TypeResult)
|
||||
return {};
|
||||
return {{std::move(TypeResult), Result->PayloadAddress}};
|
||||
@@ -1139,8 +1126,7 @@ public:
|
||||
if (!OptMetaAndValue)
|
||||
return false;
|
||||
|
||||
auto InstanceTR = readTypeFromMetadata(
|
||||
OptMetaAndValue->MetadataAddress.getAddressData());
|
||||
auto InstanceTR = readTypeFromMetadata(OptMetaAndValue->MetadataAddress);
|
||||
if (!InstanceTR)
|
||||
return false;
|
||||
|
||||
@@ -1156,8 +1142,7 @@ public:
|
||||
|
||||
// FIXME: Check third value, 'IsBridgedError'
|
||||
|
||||
auto InstanceTR = readTypeFromMetadata(
|
||||
OptMetaAndValue->MetadataAddress.getAddressData());
|
||||
auto InstanceTR = readTypeFromMetadata(OptMetaAndValue->MetadataAddress);
|
||||
if (!InstanceTR)
|
||||
return false;
|
||||
|
||||
@@ -1192,10 +1177,10 @@ public:
|
||||
};
|
||||
|
||||
auto DereferenceAndSet = [&](RemoteAddress &Address) {
|
||||
auto PointerValue = readResolvedPointerValue(Address.getAddressData());
|
||||
auto PointerValue = readResolvedPointerValue(Address);
|
||||
if (!PointerValue)
|
||||
return false;
|
||||
Address = RemoteAddress(*PointerValue);
|
||||
Address = *PointerValue;
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -1332,7 +1317,7 @@ public:
|
||||
return dyn_cast_or_null<const RecordTypeInfo>(TypeInfo);
|
||||
}
|
||||
|
||||
bool metadataIsActor(StoredPointer MetadataAddress) {
|
||||
bool metadataIsActor(RemoteAddress MetadataAddress) {
|
||||
auto Metadata = readMetadata(MetadataAddress);
|
||||
if (!Metadata)
|
||||
return false;
|
||||
@@ -1345,12 +1330,11 @@ public:
|
||||
super::readAddressOfNominalTypeDescriptor(Metadata);
|
||||
if (!DescriptorAddress)
|
||||
return false;
|
||||
if (!ownsAddress(RemoteAddress(DescriptorAddress), textRanges))
|
||||
if (!ownsAddress(DescriptorAddress, textRanges))
|
||||
return false;
|
||||
|
||||
auto DescriptorBytes =
|
||||
getReader().readBytes(RemoteAddress(DescriptorAddress),
|
||||
sizeof(TargetTypeContextDescriptor<Runtime>));
|
||||
auto DescriptorBytes = getReader().readBytes(
|
||||
DescriptorAddress, sizeof(TargetTypeContextDescriptor<Runtime>));
|
||||
if (!DescriptorBytes)
|
||||
return false;
|
||||
auto Descriptor =
|
||||
@@ -1361,12 +1345,13 @@ public:
|
||||
|
||||
/// Iterate the protocol conformance cache tree rooted at NodePtr, calling
|
||||
/// Call with the type and protocol in each node.
|
||||
void iterateConformanceTree(StoredPointer NodePtr,
|
||||
std::function<void(StoredPointer Type, StoredPointer Proto)> Call) {
|
||||
void iterateConformanceTree(
|
||||
RemoteAddress NodePtr,
|
||||
std::function<void(RemoteAddress Type, RemoteAddress Proto)> Call) {
|
||||
if (!NodePtr)
|
||||
return;
|
||||
auto NodeBytes = getReader().readBytes(RemoteAddress(NodePtr),
|
||||
sizeof(ConformanceNode<Runtime>));
|
||||
auto NodeBytes =
|
||||
getReader().readBytes(NodePtr, sizeof(ConformanceNode<Runtime>));
|
||||
if (!NodeBytes)
|
||||
return;
|
||||
auto NodeData =
|
||||
@@ -1378,8 +1363,8 @@ public:
|
||||
|
||||
void IterateConformanceTable(
|
||||
RemoteAddress ConformancesPtr,
|
||||
std::function<void(StoredPointer Type, StoredPointer Proto)> Call) {
|
||||
auto MapBytes = getReader().readBytes(RemoteAddress(ConformancesPtr),
|
||||
std::function<void(RemoteAddress Type, RemoteAddress Proto)> Call) {
|
||||
auto MapBytes = getReader().readBytes(ConformancesPtr,
|
||||
sizeof(ConcurrentHashMap<Runtime>));
|
||||
if (!MapBytes)
|
||||
return;
|
||||
@@ -1389,8 +1374,9 @@ public:
|
||||
auto Count = MapData->ElementCount;
|
||||
auto Size = Count * sizeof(ConformanceCacheEntry<Runtime>) + sizeof(StoredPointer);
|
||||
|
||||
auto ElementsBytes =
|
||||
getReader().readBytes(RemoteAddress(MapData->Elements), Size);
|
||||
auto ElementsBytes = getReader().readBytes(
|
||||
RemoteAddress(MapData->Elements, ConformancesPtr.getAddressSpace()),
|
||||
Size);
|
||||
if (!ElementsBytes)
|
||||
return;
|
||||
auto ElementsData =
|
||||
@@ -1399,7 +1385,8 @@ public:
|
||||
|
||||
for (StoredSize i = 0; i < Count; i++) {
|
||||
auto &Element = ElementsData[i];
|
||||
Call(Element.Type, Element.Proto);
|
||||
Call(RemoteAddress(Element.Type, ConformancesPtr.getAddressSpace()),
|
||||
RemoteAddress(Element.Proto, ConformancesPtr.getAddressSpace()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1407,7 +1394,7 @@ public:
|
||||
/// with the type and protocol of each conformance. Returns None on success,
|
||||
/// and a string describing the error on failure.
|
||||
std::optional<std::string> iterateConformances(
|
||||
std::function<void(StoredPointer Type, StoredPointer Proto)> Call) {
|
||||
std::function<void(RemoteAddress Type, RemoteAddress Proto)> Call) {
|
||||
std::string ConformancesPointerName =
|
||||
"_swift_debug_protocolConformanceStatePointer";
|
||||
auto ConformancesAddrAddr =
|
||||
@@ -1429,15 +1416,15 @@ public:
|
||||
StoredPointer allocationMetadataPointer(
|
||||
MetadataAllocation<Runtime> Allocation) {
|
||||
if (Allocation.Tag == GenericMetadataCacheTag) {
|
||||
auto AllocationBytes =
|
||||
getReader().readBytes(RemoteAddress(Allocation.Ptr),
|
||||
Allocation.Size);
|
||||
if (!AllocationBytes)
|
||||
return 0;
|
||||
auto Entry =
|
||||
auto AllocationBytes = getReader().readBytes(
|
||||
RemoteAddress(Allocation.Ptr, RemoteAddress::DefaultAddressSpace),
|
||||
Allocation.Size);
|
||||
if (!AllocationBytes)
|
||||
return 0;
|
||||
auto Entry =
|
||||
reinterpret_cast<const GenericMetadataCacheEntry<StoredPointer> *>(
|
||||
AllocationBytes.get());
|
||||
return Entry->Value;
|
||||
AllocationBytes.get());
|
||||
return Entry->Value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1474,7 +1461,8 @@ public:
|
||||
case ForeignMetadataCacheTag:
|
||||
case GenericWitnessTableCacheTag: {
|
||||
auto NodeBytes = getReader().readBytes(
|
||||
RemoteAddress(Allocation.Ptr), sizeof(MetadataCacheNode<Runtime>));
|
||||
RemoteAddress(Allocation.Ptr, RemoteAddress::DefaultAddressSpace),
|
||||
sizeof(MetadataCacheNode<Runtime>));
|
||||
if (!NodeBytes)
|
||||
return std::nullopt;
|
||||
auto Node =
|
||||
@@ -1517,14 +1505,14 @@ public:
|
||||
return "failed to read value of " + AllocationPoolPointerName;
|
||||
|
||||
struct PoolRange {
|
||||
StoredPointer Begin;
|
||||
RemoteAddress Begin;
|
||||
StoredSize Remaining;
|
||||
};
|
||||
struct PoolTrailer {
|
||||
StoredPointer PrevTrailer;
|
||||
RemoteAddress PrevTrailer;
|
||||
StoredSize PoolSize;
|
||||
};
|
||||
struct alignas(StoredPointer) AllocationHeader {
|
||||
struct alignas(RemoteAddress) AllocationHeader {
|
||||
uint16_t Size;
|
||||
uint16_t Tag;
|
||||
};
|
||||
@@ -1544,14 +1532,13 @@ public:
|
||||
|
||||
auto TrailerPtr = Pool->Begin + Pool->Remaining;
|
||||
while (TrailerPtr && LoopCount++ < LoopLimit) {
|
||||
auto TrailerBytes = getReader()
|
||||
.readBytes(RemoteAddress(TrailerPtr), sizeof(PoolTrailer));
|
||||
auto TrailerBytes =
|
||||
getReader().readBytes(TrailerPtr, sizeof(PoolTrailer));
|
||||
if (!TrailerBytes)
|
||||
break;
|
||||
auto Trailer = reinterpret_cast<const PoolTrailer *>(TrailerBytes.get());
|
||||
auto PoolStart = TrailerPtr - Trailer->PoolSize;
|
||||
auto PoolBytes = getReader()
|
||||
.readBytes(RemoteAddress(PoolStart), Trailer->PoolSize);
|
||||
auto PoolBytes = getReader().readBytes(PoolStart, Trailer->PoolSize);
|
||||
if (!PoolBytes)
|
||||
break;
|
||||
auto PoolPtr = (const char *)PoolBytes.get();
|
||||
@@ -1565,7 +1552,10 @@ public:
|
||||
auto RemoteAddr = PoolStart + Offset + sizeof(AllocationHeader);
|
||||
MetadataAllocation<Runtime> Allocation;
|
||||
Allocation.Tag = Header->Tag;
|
||||
Allocation.Ptr = RemoteAddr;
|
||||
|
||||
if (RemoteAddr.getAddressSpace() != RemoteAddress::DefaultAddressSpace)
|
||||
return "storing remote address from non-default address space.";
|
||||
Allocation.Ptr = RemoteAddr.getRawAddress();
|
||||
Allocation.Size = Header->Size;
|
||||
Call(Allocation);
|
||||
|
||||
@@ -1601,15 +1591,15 @@ public:
|
||||
auto BacktraceListNext = BacktraceListNextPtr->getResolvedAddress();
|
||||
while (BacktraceListNext && LoopCount++ < LoopLimit) {
|
||||
auto HeaderBytes = getReader().readBytes(
|
||||
RemoteAddress(BacktraceListNext),
|
||||
BacktraceListNext,
|
||||
sizeof(MetadataAllocationBacktraceHeader<Runtime>));
|
||||
if (!HeaderBytes) {
|
||||
// FIXME: std::stringstream would be better, but LLVM's standard library
|
||||
// introduces a vtable and we don't want that.
|
||||
char result[128];
|
||||
std::snprintf(result, sizeof(result),
|
||||
"unable to read Next pointer %#" PRIx64,
|
||||
BacktraceListNext.getAddressData());
|
||||
"unable to read Next pointer %#" PRIx64,
|
||||
BacktraceListNext.getRawAddress());
|
||||
return std::string(result);
|
||||
}
|
||||
auto HeaderPtr =
|
||||
@@ -1618,15 +1608,15 @@ public:
|
||||
auto BacktraceAddrPtr =
|
||||
BacktraceListNext +
|
||||
sizeof(MetadataAllocationBacktraceHeader<Runtime>);
|
||||
auto BacktraceBytes =
|
||||
getReader().readBytes(RemoteAddress(BacktraceAddrPtr),
|
||||
HeaderPtr->Count * sizeof(StoredPointer));
|
||||
auto BacktraceBytes = getReader().readBytes(
|
||||
BacktraceAddrPtr, HeaderPtr->Count * sizeof(StoredPointer));
|
||||
auto BacktracePtr =
|
||||
reinterpret_cast<const StoredPointer *>(BacktraceBytes.get());
|
||||
|
||||
Call(HeaderPtr->Allocation, HeaderPtr->Count, BacktracePtr);
|
||||
|
||||
BacktraceListNext = RemoteAddress(HeaderPtr->Next);
|
||||
BacktraceListNext =
|
||||
RemoteAddress(HeaderPtr->Next, RemoteAddress::DefaultAddressSpace);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -1635,7 +1625,8 @@ public:
|
||||
asyncTaskSlabAllocations(StoredPointer SlabPtr) {
|
||||
using StackAllocator = StackAllocator<Runtime>;
|
||||
auto SlabBytes = getReader().readBytes(
|
||||
RemoteAddress(SlabPtr), sizeof(typename StackAllocator::Slab));
|
||||
RemoteAddress(SlabPtr, RemoteAddress::DefaultAddressSpace),
|
||||
sizeof(typename StackAllocator::Slab));
|
||||
auto Slab = reinterpret_cast<const typename StackAllocator::Slab *>(
|
||||
SlabBytes.get());
|
||||
if (!Slab)
|
||||
@@ -1660,14 +1651,14 @@ public:
|
||||
NextPtrChunk.Kind = AsyncTaskAllocationChunk::ChunkKind::RawPointer;
|
||||
|
||||
// Total slab size is the slab's capacity plus the header.
|
||||
StoredPointer SlabSize = Slab->Capacity + HeaderSize;
|
||||
auto SlabSize = Slab->Capacity + HeaderSize;
|
||||
|
||||
return {std::nullopt,
|
||||
{Slab->Next, SlabSize, {NextPtrChunk, AllocatedSpaceChunk}}};
|
||||
}
|
||||
|
||||
std::pair<std::optional<std::string>, AsyncTaskInfo>
|
||||
asyncTaskInfo(StoredPointer AsyncTaskPtr, unsigned ChildTaskLimit,
|
||||
asyncTaskInfo(RemoteAddress AsyncTaskPtr, unsigned ChildTaskLimit,
|
||||
unsigned AsyncBacktraceLimit) {
|
||||
loadTargetPointers();
|
||||
|
||||
@@ -1682,7 +1673,7 @@ public:
|
||||
}
|
||||
|
||||
std::pair<std::optional<std::string>, ActorInfo>
|
||||
actorInfo(StoredPointer ActorPtr) {
|
||||
actorInfo(RemoteAddress ActorPtr) {
|
||||
if (supportsPriorityEscalation)
|
||||
return actorInfo<
|
||||
DefaultActorImpl<Runtime, ActiveActorStatusWithEscalation<Runtime>>>(
|
||||
@@ -1692,10 +1683,10 @@ public:
|
||||
Runtime, ActiveActorStatusWithoutEscalation<Runtime>>>(ActorPtr);
|
||||
}
|
||||
|
||||
StoredPointer nextJob(StoredPointer JobPtr) {
|
||||
StoredPointer nextJob(RemoteAddress JobPtr) {
|
||||
using Job = Job<Runtime>;
|
||||
|
||||
auto JobBytes = getReader().readBytes(RemoteAddress(JobPtr), sizeof(Job));
|
||||
auto JobBytes = getReader().readBytes(JobPtr, sizeof(Job));
|
||||
auto *JobObj = reinterpret_cast<const Job *>(JobBytes.get());
|
||||
if (!JobObj)
|
||||
return 0;
|
||||
@@ -1770,7 +1761,7 @@ private:
|
||||
|
||||
template <typename AsyncTaskType>
|
||||
std::pair<std::optional<std::string>, AsyncTaskInfo>
|
||||
asyncTaskInfo(StoredPointer AsyncTaskPtr, unsigned ChildTaskLimit,
|
||||
asyncTaskInfo(RemoteAddress AsyncTaskPtr, unsigned ChildTaskLimit,
|
||||
unsigned AsyncBacktraceLimit) {
|
||||
auto AsyncTaskObj = readObj<AsyncTaskType>(AsyncTaskPtr);
|
||||
if (!AsyncTaskObj)
|
||||
@@ -1805,7 +1796,8 @@ private:
|
||||
|
||||
// Find all child tasks.
|
||||
unsigned ChildTaskLoopCount = 0;
|
||||
auto RecordPtr = AsyncTaskObj->PrivateStorage.Status.Record;
|
||||
auto RecordPtr = RemoteAddress(AsyncTaskObj->PrivateStorage.Status.Record,
|
||||
RemoteAddress::DefaultAddressSpace);
|
||||
while (RecordPtr && ChildTaskLoopCount++ < ChildTaskLimit) {
|
||||
auto RecordObj = readObj<TaskStatusRecord<Runtime>>(RecordPtr);
|
||||
if (!RecordObj)
|
||||
@@ -1829,8 +1821,10 @@ private:
|
||||
}
|
||||
|
||||
while (ChildTask && ChildTaskLoopCount++ < ChildTaskLimit) {
|
||||
RemoteAddress ChildTaskAddress =
|
||||
RemoteAddress(ChildTask, RemoteAddress::DefaultAddressSpace);
|
||||
// Read the child task.
|
||||
auto ChildTaskObj = readObj<AsyncTaskType>(ChildTask);
|
||||
auto ChildTaskObj = readObj<AsyncTaskType>(ChildTaskAddress);
|
||||
if (!ChildTaskObj)
|
||||
return {std::string("found unreadable child task pointer"), Info};
|
||||
|
||||
@@ -1843,7 +1837,7 @@ private:
|
||||
"iterate child tasks"),
|
||||
Info};
|
||||
|
||||
StoredPointer ChildFragmentAddr = ChildTask + asyncTaskSize;
|
||||
RemoteAddress ChildFragmentAddr = ChildTaskAddress + asyncTaskSize;
|
||||
auto ChildFragmentObj =
|
||||
readObj<ChildFragment<Runtime>>(ChildFragmentAddr);
|
||||
if (ChildFragmentObj)
|
||||
@@ -1856,7 +1850,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
RecordPtr = RecordObj->Parent;
|
||||
RecordPtr =
|
||||
RemoteAddress(RecordObj->Parent, RemoteAddress::DefaultAddressSpace);
|
||||
}
|
||||
|
||||
const auto TaskResumeContext = AsyncTaskObj->ResumeContextAndReserved[0];
|
||||
@@ -1867,12 +1862,14 @@ private:
|
||||
auto ResumeContext = TaskResumeContext;
|
||||
unsigned AsyncBacktraceLoopCount = 0;
|
||||
while (ResumeContext && AsyncBacktraceLoopCount++ < AsyncBacktraceLimit) {
|
||||
auto ResumeContextObj = readObj<AsyncContext<Runtime>>(ResumeContext);
|
||||
auto ResumeContextObj = readObj<AsyncContext<Runtime>>(
|
||||
RemoteAddress(ResumeContext, RemoteAddress::DefaultAddressSpace));
|
||||
if (!ResumeContextObj)
|
||||
break;
|
||||
Info.AsyncBacktraceFrames.push_back(
|
||||
stripSignedPointer(ResumeContextObj->ResumeParent));
|
||||
ResumeContext = stripSignedPointer(ResumeContextObj->Parent);
|
||||
stripSignedPointer(ResumeContextObj->ResumeParent).getRawAddress());
|
||||
ResumeContext =
|
||||
stripSignedPointer(ResumeContextObj->Parent).getRawAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1881,7 +1878,7 @@ private:
|
||||
|
||||
template <typename ActorType>
|
||||
std::pair<std::optional<std::string>, ActorInfo>
|
||||
actorInfo(StoredPointer ActorPtr) {
|
||||
actorInfo(RemoteAddress ActorPtr) {
|
||||
auto ActorObj = readObj<ActorType>(ActorPtr);
|
||||
if (!ActorObj)
|
||||
return {std::string("failure reading actor"), {}};
|
||||
@@ -1900,7 +1897,7 @@ private:
|
||||
// Don't read FirstJob when idle.
|
||||
if (Info.State != concurrency::ActorFlagConstants::Idle) {
|
||||
// This is a JobRef which stores flags in the low bits.
|
||||
Info.FirstJob = ActorObj->Status.FirstJob & ~StoredPointer(0x3);
|
||||
Info.FirstJob = ActorObj->Status.FirstJob & ~0x3;
|
||||
}
|
||||
|
||||
std::tie(Info.HasThreadPort, Info.ThreadPort) =
|
||||
@@ -1913,27 +1910,29 @@ private:
|
||||
// like AsyncTask::getResumeFunctionForLogging does.
|
||||
template <typename AsyncTaskType>
|
||||
StoredPointer getRunJob(const AsyncTaskType *AsyncTaskObj) {
|
||||
auto Fptr = stripSignedPointer(AsyncTaskObj->RunJob);
|
||||
auto Fptr = stripSignedPointer(AsyncTaskObj->RunJob).getRawAddress();
|
||||
|
||||
loadTargetPointers();
|
||||
auto ResumeContextPtr = AsyncTaskObj->ResumeContextAndReserved[0];
|
||||
if (target_non_future_adapter && Fptr == target_non_future_adapter) {
|
||||
using Prefix = AsyncContextPrefix<Runtime>;
|
||||
auto PrefixAddr = ResumeContextPtr - sizeof(Prefix);
|
||||
auto PrefixBytes =
|
||||
getReader().readBytes(RemoteAddress(PrefixAddr), sizeof(Prefix));
|
||||
auto PrefixBytes = getReader().readBytes(
|
||||
RemoteAddress(PrefixAddr, RemoteAddress::DefaultAddressSpace),
|
||||
sizeof(Prefix));
|
||||
if (PrefixBytes) {
|
||||
auto PrefixPtr = reinterpret_cast<const Prefix *>(PrefixBytes.get());
|
||||
return stripSignedPointer(PrefixPtr->AsyncEntryPoint);
|
||||
return stripSignedPointer(PrefixPtr->AsyncEntryPoint).getRawAddress();
|
||||
}
|
||||
} else if (target_future_adapter && Fptr == target_future_adapter) {
|
||||
using Prefix = FutureAsyncContextPrefix<Runtime>;
|
||||
auto PrefixAddr = ResumeContextPtr - sizeof(Prefix);
|
||||
auto PrefixBytes =
|
||||
getReader().readBytes(RemoteAddress(PrefixAddr), sizeof(Prefix));
|
||||
auto PrefixBytes = getReader().readBytes(
|
||||
RemoteAddress(PrefixAddr, RemoteAddress::DefaultAddressSpace),
|
||||
sizeof(Prefix));
|
||||
if (PrefixBytes) {
|
||||
auto PrefixPtr = reinterpret_cast<const Prefix *>(PrefixBytes.get());
|
||||
return stripSignedPointer(PrefixPtr->AsyncEntryPoint);
|
||||
return stripSignedPointer(PrefixPtr->AsyncEntryPoint).getRawAddress();
|
||||
}
|
||||
} else if ((target_task_wait_throwing_resume_adapter &&
|
||||
Fptr == target_task_wait_throwing_resume_adapter) ||
|
||||
@@ -1944,11 +1943,12 @@ private:
|
||||
// and the pointers are potentially stale.
|
||||
if (AsyncTaskObj->PrivateStorage.DependencyRecord) {
|
||||
auto ContextBytes = getReader().readBytes(
|
||||
RemoteAddress(ResumeContextPtr), sizeof(AsyncContext<Runtime>));
|
||||
RemoteAddress(ResumeContextPtr, RemoteAddress::DefaultAddressSpace),
|
||||
sizeof(AsyncContext<Runtime>));
|
||||
if (ContextBytes) {
|
||||
auto ContextPtr = reinterpret_cast<const AsyncContext<Runtime> *>(
|
||||
ContextBytes.get());
|
||||
return stripSignedPointer(ContextPtr->ResumeParent);
|
||||
return stripSignedPointer(ContextPtr->ResumeParent).getRawAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1967,7 +1967,7 @@ private:
|
||||
auto Pointer = getReader().readPointer(Symbol, sizeof(StoredPointer));
|
||||
if (!Pointer)
|
||||
return 0;
|
||||
return Pointer->getResolvedAddress().getAddressData();
|
||||
return Pointer->getResolvedAddress().getRawAddress();
|
||||
};
|
||||
target_asyncTaskMetadata =
|
||||
getPointer("_swift_concurrency_debug_asyncTaskMetadata");
|
||||
@@ -1995,7 +1995,7 @@ private:
|
||||
}
|
||||
|
||||
const TypeInfo *
|
||||
getClosureContextInfo(StoredPointer Context, const ClosureContextInfo &Info,
|
||||
getClosureContextInfo(RemoteAddress Context, const ClosureContextInfo &Info,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
RecordTypeInfoBuilder Builder(getBuilder().getTypeConverter(),
|
||||
RecordKind::ClosureContext);
|
||||
@@ -2144,8 +2144,8 @@ private:
|
||||
/// above.
|
||||
///
|
||||
/// \param Builder Used to obtain offsets of elements known so far.
|
||||
std::optional<StoredPointer>
|
||||
readMetadataSource(StoredPointer Context, const MetadataSource *MS,
|
||||
std::optional<RemoteAddress>
|
||||
readMetadataSource(RemoteAddress Context, const MetadataSource *MS,
|
||||
const RecordTypeInfoBuilder &Builder) {
|
||||
switch (MS->getKind()) {
|
||||
case MetadataSourceKind::ClosureBinding: {
|
||||
@@ -2161,9 +2161,9 @@ private:
|
||||
unsigned Offset = getSizeOfHeapObject() +
|
||||
sizeof(StoredPointer) * Index;
|
||||
|
||||
StoredPointer MetadataAddress;
|
||||
if (!getReader().readInteger(RemoteAddress(Context + Offset),
|
||||
&MetadataAddress))
|
||||
RemoteAddress MetadataAddress;
|
||||
if (!getReader().template readRemoteAddress<StoredPointer>(
|
||||
Context + Offset, MetadataAddress))
|
||||
break;
|
||||
|
||||
return MetadataAddress;
|
||||
@@ -2175,9 +2175,9 @@ private:
|
||||
// of this capture in the context.
|
||||
unsigned CaptureOffset = Builder.getFieldOffset(Index);
|
||||
|
||||
StoredPointer CaptureAddress;
|
||||
if (!getReader().readInteger(RemoteAddress(Context + CaptureOffset),
|
||||
&CaptureAddress))
|
||||
RemoteAddress CaptureAddress;
|
||||
if (!getReader().template readRemoteAddress<StoredPointer>(
|
||||
Context + CaptureOffset, CaptureAddress))
|
||||
break;
|
||||
|
||||
// Read the requested capture's isa pointer.
|
||||
@@ -2190,9 +2190,9 @@ private:
|
||||
// of this capture in the context.
|
||||
unsigned CaptureOffset = Builder.getFieldOffset(Index);
|
||||
|
||||
StoredPointer CaptureAddress;
|
||||
if (!getReader().readInteger(RemoteAddress(Context + CaptureOffset),
|
||||
&CaptureAddress))
|
||||
RemoteAddress CaptureAddress;
|
||||
if (!getReader().template readRemoteAddress<StoredPointer>(
|
||||
Context + CaptureOffset, CaptureAddress))
|
||||
break;
|
||||
|
||||
return CaptureAddress;
|
||||
@@ -2219,8 +2219,8 @@ private:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MemoryReader::ReadObjResult<T> readObj(StoredPointer Ptr) {
|
||||
return getReader().template readObj<T>(RemoteAddress(Ptr));
|
||||
MemoryReader::ReadObjResult<T> readObj(RemoteAddress Ptr) {
|
||||
return getReader().template readObj<T>(Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -63,16 +63,21 @@ public:
|
||||
|
||||
size_t size() const { return Size; }
|
||||
|
||||
bool containsRemoteAddress(uint64_t remoteAddr, uint64_t size) const {
|
||||
return Start.getAddressData() <= remoteAddr &&
|
||||
remoteAddr + size <= Start.getAddressData() + Size;
|
||||
bool containsRemoteAddress(remote::RemoteAddress remoteAddr,
|
||||
uint64_t size) const {
|
||||
if (Start.getRemoteAddress().getAddressSpace() !=
|
||||
remoteAddr.getAddressSpace())
|
||||
return false;
|
||||
|
||||
return Start.getRemoteAddress() <= remoteAddr &&
|
||||
remoteAddr + size <= Start.getRemoteAddress() + Size;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RemoteRef<U> getRemoteRef(uint64_t remoteAddr) const {
|
||||
RemoteRef<U> getRemoteRef(remote::RemoteAddress remoteAddr) const {
|
||||
assert(containsRemoteAddress(remoteAddr, sizeof(U)));
|
||||
auto localAddr = (uint64_t)(uintptr_t)Start.getLocalBuffer() +
|
||||
(remoteAddr - Start.getAddressData());
|
||||
(remoteAddr - Start.getRemoteAddress()).getRawAddress();
|
||||
|
||||
return RemoteRef<U>(remoteAddr, (const U *)localAddr);
|
||||
}
|
||||
@@ -124,7 +129,7 @@ public:
|
||||
|
||||
RemoteRef<Descriptor> operator*() const {
|
||||
assert(Size > 0);
|
||||
return RemoteRef<Descriptor>(Cur.getAddressData(),
|
||||
return RemoteRef<Descriptor>(Cur.getRemoteAddress(),
|
||||
(const Descriptor *)Cur.getLocalBuffer());
|
||||
}
|
||||
|
||||
@@ -499,7 +504,8 @@ public:
|
||||
|
||||
/// Get the raw capture descriptor for a remote capture descriptor
|
||||
/// address.
|
||||
RemoteRef<CaptureDescriptor> getCaptureDescriptor(uint64_t RemoteAddress);
|
||||
RemoteRef<CaptureDescriptor>
|
||||
getCaptureDescriptor(remote::RemoteAddress RemoteAddress);
|
||||
|
||||
/// Get the unsubstituted capture types for a closure context.
|
||||
ClosureContextInfo getClosureContextInfo(RemoteRef<CaptureDescriptor> CD);
|
||||
@@ -512,11 +518,11 @@ public:
|
||||
const std::string &Member,
|
||||
StringRef Protocol);
|
||||
|
||||
RemoteRef<char> readTypeRef(uint64_t remoteAddr);
|
||||
RemoteRef<char> readTypeRef(remote::RemoteAddress remoteAddr);
|
||||
|
||||
template <typename Record, typename Field>
|
||||
RemoteRef<char> readTypeRef(RemoteRef<Record> record, const Field &field) {
|
||||
uint64_t remoteAddr = record.resolveRelativeFieldData(field);
|
||||
remote::RemoteAddress remoteAddr = record.resolveRelativeFieldData(field);
|
||||
|
||||
return readTypeRef(remoteAddr);
|
||||
}
|
||||
@@ -544,7 +550,8 @@ public:
|
||||
StringRef searchName);
|
||||
|
||||
std::optional<std::reference_wrapper<const ReflectionInfo>>
|
||||
findReflectionInfoWithTypeRefContainingAddress(uint64_t remoteAddr);
|
||||
findReflectionInfoWithTypeRefContainingAddress(
|
||||
remote::RemoteAddress remoteAddr);
|
||||
|
||||
std::vector<ReflectionInfo> ReflectionInfos;
|
||||
|
||||
@@ -555,8 +562,7 @@ public:
|
||||
llvm::DenseSet<size_t> ProcessedReflectionInfoIndexes;
|
||||
|
||||
/// Cache for capture descriptor lookups.
|
||||
std::unordered_map<uint64_t /* remote address*/,
|
||||
RemoteRef<CaptureDescriptor>>
|
||||
std::unordered_map<remote::RemoteAddress, RemoteRef<CaptureDescriptor>>
|
||||
CaptureDescriptorsByAddress;
|
||||
uint32_t CaptureDescriptorsByAddressLastReflectionInfoCache = 0;
|
||||
|
||||
@@ -565,7 +571,7 @@ public:
|
||||
FieldTypeInfoCache;
|
||||
|
||||
/// Cache for normalized reflection name lookups.
|
||||
std::unordered_map<uint64_t /* remote address */,
|
||||
std::unordered_map<remote::RemoteAddress /* remote address */,
|
||||
std::optional<std::string>>
|
||||
NormalizedReflectionNameCache;
|
||||
|
||||
@@ -1107,8 +1113,12 @@ public:
|
||||
// Try to resolve to the underlying type, if we can.
|
||||
if (opaqueDescriptor->getKind() ==
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
|
||||
auto underlyingTy =
|
||||
OpaqueUnderlyingTypeReader(opaqueDescriptor->getIndex(), ordinal);
|
||||
// FIXME: Node should carry a data structure that can fit a remote
|
||||
// address. For now assume that this is a virtual address.
|
||||
auto underlyingTy = OpaqueUnderlyingTypeReader(
|
||||
remote::RemoteAddress(opaqueDescriptor->getIndex(),
|
||||
remote::RemoteAddress::DefaultAddressSpace),
|
||||
ordinal);
|
||||
|
||||
if (!underlyingTy)
|
||||
return nullptr;
|
||||
@@ -1457,7 +1467,7 @@ private:
|
||||
llvm::DenseSet<size_t> ProcessedReflectionInfoIndexes;
|
||||
|
||||
public:
|
||||
RemoteRef<char> readTypeRef(uint64_t remoteAddr) {
|
||||
RemoteRef<char> readTypeRef(remote::RemoteAddress remoteAddr) {
|
||||
return RDF.readTypeRef(remoteAddr);
|
||||
}
|
||||
template <typename Record, typename Field>
|
||||
@@ -1471,7 +1481,7 @@ public:
|
||||
private:
|
||||
using RefDemangler = std::function<Demangle::Node *(RemoteRef<char>, bool)>;
|
||||
using UnderlyingTypeReader =
|
||||
std::function<const TypeRef *(uint64_t, unsigned)>;
|
||||
std::function<const TypeRef *(remote::RemoteAddress, unsigned)>;
|
||||
using ByteReader = std::function<remote::MemoryReader::ReadBytesResult(
|
||||
remote::RemoteAddress, unsigned)>;
|
||||
using StringReader =
|
||||
@@ -1528,7 +1538,7 @@ public:
|
||||
useOpaqueTypeSymbolicReferences);
|
||||
}),
|
||||
OpaqueUnderlyingTypeReader(
|
||||
[&reader](uint64_t descriptorAddr,
|
||||
[&reader](remote::RemoteAddress descriptorAddr,
|
||||
unsigned ordinal) -> const TypeRef * {
|
||||
return reader
|
||||
.readUnderlyingTypeForOpaqueTypeDescriptor(descriptorAddr,
|
||||
@@ -1616,7 +1626,8 @@ public:
|
||||
|
||||
/// Get the raw capture descriptor for a remote capture descriptor
|
||||
/// address.
|
||||
RemoteRef<CaptureDescriptor> getCaptureDescriptor(uint64_t RemoteAddress) {
|
||||
RemoteRef<CaptureDescriptor>
|
||||
getCaptureDescriptor(remote::RemoteAddress RemoteAddress) {
|
||||
return RDF.getCaptureDescriptor(RemoteAddress);
|
||||
}
|
||||
|
||||
@@ -1697,8 +1708,11 @@ public:
|
||||
auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild();
|
||||
if (opaqueTypeChildDemangleTree->getKind() ==
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
|
||||
// FIXME: Node should carry a data structure that can fit a remote
|
||||
// address. For now assume that this is a process address.
|
||||
extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
|
||||
opaqueTypeChildDemangleTree->getIndex(),
|
||||
remote::RemoteAddress(opaqueTypeChildDemangleTree->getIndex(),
|
||||
remote::RemoteAddress::DefaultAddressSpace),
|
||||
opaqueTypeConformanceRequirements, sameTypeRequirements);
|
||||
}
|
||||
}
|
||||
@@ -1708,7 +1722,7 @@ public:
|
||||
private:
|
||||
struct ContextNameInfo {
|
||||
std::string name;
|
||||
uintptr_t descriptorAddress;
|
||||
remote::RemoteAddress descriptorAddress;
|
||||
bool isAnonymous;
|
||||
|
||||
~ContextNameInfo() {}
|
||||
@@ -1731,10 +1745,10 @@ private:
|
||||
OpaqueDynamicSymbolResolver(dynamicSymbolResolver) {}
|
||||
|
||||
std::optional<std::string> readProtocolNameFromProtocolDescriptor(
|
||||
uintptr_t protocolDescriptorAddress) {
|
||||
remote::RemoteAddress protocolDescriptorAddress) {
|
||||
std::string protocolName;
|
||||
auto protocolDescriptorBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(protocolDescriptorAddress),
|
||||
protocolDescriptorAddress,
|
||||
sizeof(ExternalProtocolDescriptor<ObjCInteropKind, PointerSize>));
|
||||
if (!protocolDescriptorBytes.get()) {
|
||||
Error = "Error reading protocol descriptor.";
|
||||
@@ -1747,11 +1761,11 @@ private:
|
||||
|
||||
// Compute the address of the protocol descriptor's name field and read
|
||||
// the offset
|
||||
auto protocolNameOffsetAddress = detail::applyRelativeOffset(
|
||||
(const char *)protocolDescriptorAddress,
|
||||
(int32_t)protocolDescriptor->getNameOffset());
|
||||
auto protocolNameOffsetBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(protocolNameOffsetAddress), sizeof(uint32_t));
|
||||
auto protocolNameOffsetAddress =
|
||||
protocolDescriptorAddress.applyRelativeOffset(
|
||||
(int32_t)protocolDescriptor->getNameOffset());
|
||||
auto protocolNameOffsetBytes =
|
||||
OpaqueByteReader(protocolNameOffsetAddress, sizeof(uint32_t));
|
||||
if (!protocolNameOffsetBytes.get()) {
|
||||
Error = "Failed to read type name offset in a protocol descriptor.";
|
||||
return std::nullopt;
|
||||
@@ -1760,74 +1774,71 @@ private:
|
||||
|
||||
// Using the offset above, compute the address of the name field itsel
|
||||
// and read it.
|
||||
auto protocolNameAddress =
|
||||
detail::applyRelativeOffset((const char *)protocolNameOffsetAddress,
|
||||
(int32_t)*protocolNameOffset);
|
||||
OpaqueStringReader(remote::RemoteAddress(protocolNameAddress),
|
||||
protocolName);
|
||||
auto protocolNameAddress = protocolNameOffsetAddress.applyRelativeOffset(
|
||||
(int32_t)*protocolNameOffset);
|
||||
OpaqueStringReader(protocolNameAddress, protocolName);
|
||||
return protocolName;
|
||||
}
|
||||
|
||||
std::optional<std::string> readTypeNameFromTypeDescriptor(
|
||||
const ExternalTypeContextDescriptor<ObjCInteropKind, PointerSize>
|
||||
*typeDescriptor,
|
||||
uintptr_t typeDescriptorAddress) {
|
||||
auto typeNameOffsetAddress =
|
||||
detail::applyRelativeOffset((const char *)typeDescriptorAddress,
|
||||
(int32_t)typeDescriptor->getNameOffset());
|
||||
auto typeNameOffsetBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(typeNameOffsetAddress), sizeof(uint32_t));
|
||||
remote::RemoteAddress typeDescriptorAddress) {
|
||||
auto typeNameOffsetAddress = typeDescriptorAddress.applyRelativeOffset(
|
||||
(int32_t)typeDescriptor->getNameOffset());
|
||||
auto typeNameOffsetBytes =
|
||||
OpaqueByteReader(typeNameOffsetAddress, sizeof(uint32_t));
|
||||
if (!typeNameOffsetBytes.get()) {
|
||||
Error = "Failed to read type name offset in a type descriptor.";
|
||||
return std::nullopt;
|
||||
}
|
||||
auto typeNameOffset = (const uint32_t *)typeNameOffsetBytes.get();
|
||||
auto typeNameAddress = detail::applyRelativeOffset(
|
||||
(const char *)typeNameOffsetAddress, (int32_t)*typeNameOffset);
|
||||
auto typeNameAddress =
|
||||
typeNameOffsetAddress.applyRelativeOffset((int32_t)*typeNameOffset);
|
||||
std::string typeName;
|
||||
OpaqueStringReader(remote::RemoteAddress(typeNameAddress), typeName);
|
||||
OpaqueStringReader(typeNameAddress, typeName);
|
||||
return typeName;
|
||||
}
|
||||
|
||||
std::optional<std::string> readModuleNameFromModuleDescriptor(
|
||||
const ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>
|
||||
*moduleDescriptor,
|
||||
uintptr_t moduleDescriptorAddress) {
|
||||
auto parentNameOffsetAddress = detail::applyRelativeOffset(
|
||||
(const char *)moduleDescriptorAddress,
|
||||
(int32_t)moduleDescriptor->getNameOffset());
|
||||
auto parentNameOffsetBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(parentNameOffsetAddress), sizeof(uint32_t));
|
||||
remote::RemoteAddress moduleDescriptorAddress) {
|
||||
auto parentNameOffsetAddress =
|
||||
moduleDescriptorAddress.applyRelativeOffset(
|
||||
(int32_t)moduleDescriptor->getNameOffset());
|
||||
auto parentNameOffsetBytes =
|
||||
OpaqueByteReader(parentNameOffsetAddress, sizeof(uint32_t));
|
||||
if (!parentNameOffsetBytes.get()) {
|
||||
Error = "Failed to read parent name offset in a module descriptor.";
|
||||
return std::nullopt;
|
||||
}
|
||||
auto parentNameOffset = (const uint32_t *)parentNameOffsetBytes.get();
|
||||
auto parentNameAddress = detail::applyRelativeOffset(
|
||||
(const char *)parentNameOffsetAddress, (int32_t)*parentNameOffset);
|
||||
auto parentNameAddress = parentNameOffsetAddress.applyRelativeOffset(
|
||||
(int32_t)*parentNameOffset);
|
||||
std::string parentName;
|
||||
OpaqueStringReader(remote::RemoteAddress(parentNameAddress), parentName);
|
||||
OpaqueStringReader(parentNameAddress, parentName);
|
||||
return parentName;
|
||||
}
|
||||
|
||||
std::optional<std::string> readAnonymousNameFromAnonymousDescriptor(
|
||||
const ExternalAnonymousContextDescriptor<ObjCInteropKind, PointerSize>
|
||||
*anonymousDescriptor,
|
||||
uintptr_t anonymousDescriptorAddress) {
|
||||
remote::RemoteAddress anonymousDescriptorAddress) {
|
||||
if (!anonymousDescriptor->hasMangledName()) {
|
||||
std::stringstream stream;
|
||||
stream << "(unknown context at $" << std::hex
|
||||
<< anonymousDescriptorAddress << ")";
|
||||
stream << "(unknown context at $"
|
||||
<< anonymousDescriptorAddress.getDescription() << ")";
|
||||
return stream.str();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string>
|
||||
readFullyQualifiedTypeName(uintptr_t typeDescriptorTarget) {
|
||||
readFullyQualifiedTypeName(remote::RemoteAddress typeDescriptorTarget) {
|
||||
std::string typeName;
|
||||
auto contextTypeDescriptorBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(typeDescriptorTarget),
|
||||
typeDescriptorTarget,
|
||||
sizeof(ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
|
||||
if (!contextTypeDescriptorBytes.get()) {
|
||||
Error = "Failed to read context descriptor.";
|
||||
@@ -1861,17 +1872,16 @@ private:
|
||||
return constructFullyQualifiedNameFromContextChain(contextNameChain);
|
||||
}
|
||||
|
||||
std::optional<std::string>
|
||||
readFullyQualifiedProtocolName(uintptr_t protocolDescriptorTarget) {
|
||||
std::optional<std::string> readFullyQualifiedProtocolName(
|
||||
remote::RemoteAddress protocolDescriptorTarget) {
|
||||
std::optional<std::string> protocolName;
|
||||
// Set low bit indicates that this is an indirect
|
||||
// reference
|
||||
if (protocolDescriptorTarget & 0x1) {
|
||||
auto adjustedProtocolDescriptorTarget = protocolDescriptorTarget & ~0x1;
|
||||
if (auto symbol = OpaquePointerReader(
|
||||
remote::RemoteAddress(adjustedProtocolDescriptorTarget),
|
||||
PointerSize)) {
|
||||
if (!symbol->getSymbol().empty()) {
|
||||
if (auto symbol = OpaquePointerReader(adjustedProtocolDescriptorTarget,
|
||||
PointerSize)) {
|
||||
if (!symbol->getSymbol().empty() && symbol->getOffset() == 0) {
|
||||
Demangle::Context Ctx;
|
||||
auto demangledRoot =
|
||||
Ctx.demangleSymbolAsNode(symbol->getSymbol().str());
|
||||
@@ -1882,7 +1892,7 @@ private:
|
||||
nodeToString(demangledRoot->getChild(0)->getChild(0));
|
||||
} else {
|
||||
// This is an absolute address of a protocol descriptor
|
||||
auto protocolDescriptorAddress = (uintptr_t)symbol->getOffset();
|
||||
auto protocolDescriptorAddress = symbol->getResolvedAddress();
|
||||
protocolName = readFullyQualifiedProtocolNameFromProtocolDescriptor(
|
||||
protocolDescriptorAddress);
|
||||
}
|
||||
@@ -1902,13 +1912,13 @@ private:
|
||||
private:
|
||||
std::optional<std::string>
|
||||
readFullyQualifiedProtocolNameFromProtocolDescriptor(
|
||||
uintptr_t protocolDescriptorAddress) {
|
||||
remote::RemoteAddress protocolDescriptorAddress) {
|
||||
std::optional<std::string> protocolName =
|
||||
readProtocolNameFromProtocolDescriptor(protocolDescriptorAddress);
|
||||
|
||||
// Read the protocol conformance descriptor itself
|
||||
auto protocolContextDescriptorBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(protocolDescriptorAddress),
|
||||
protocolDescriptorAddress,
|
||||
sizeof(ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
|
||||
if (!protocolContextDescriptorBytes.get()) {
|
||||
return std::nullopt;
|
||||
@@ -1926,23 +1936,22 @@ private:
|
||||
return constructFullyQualifiedNameFromContextChain(contextNameChain);
|
||||
}
|
||||
|
||||
uintptr_t getParentDescriptorAddress(
|
||||
uintptr_t contextDescriptorAddress,
|
||||
remote::RemoteAddress getParentDescriptorAddress(
|
||||
remote::RemoteAddress contextDescriptorAddress,
|
||||
const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
|
||||
*contextDescriptor) {
|
||||
auto parentOffsetAddress = detail::applyRelativeOffset(
|
||||
(const char *)contextDescriptorAddress,
|
||||
auto parentOffsetAddress = contextDescriptorAddress.applyRelativeOffset(
|
||||
(int32_t)contextDescriptor->getParentOffset());
|
||||
auto parentOfsetBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(parentOffsetAddress), sizeof(uint32_t));
|
||||
auto parentOfsetBytes =
|
||||
OpaqueByteReader(parentOffsetAddress, sizeof(uint32_t));
|
||||
auto parentFieldOffset = (const int32_t *)parentOfsetBytes.get();
|
||||
auto parentTargetAddress = detail::applyRelativeOffset(
|
||||
(const char *)parentOffsetAddress, *parentFieldOffset);
|
||||
auto parentTargetAddress =
|
||||
parentOffsetAddress.applyRelativeOffset(*parentFieldOffset);
|
||||
return parentTargetAddress;
|
||||
}
|
||||
|
||||
std::optional<ContextNameInfo>
|
||||
getContextName(uintptr_t contextDescriptorAddress,
|
||||
getContextName(remote::RemoteAddress contextDescriptorAddress,
|
||||
const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
|
||||
*contextDescriptor) {
|
||||
if (auto moduleDescriptor = dyn_cast<
|
||||
@@ -1988,7 +1997,7 @@ private:
|
||||
}
|
||||
|
||||
void getParentContextChain(
|
||||
uintptr_t contextDescriptorAddress,
|
||||
remote::RemoteAddress contextDescriptorAddress,
|
||||
const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
|
||||
*contextDescriptor,
|
||||
std::vector<ContextNameInfo> &chain) {
|
||||
@@ -1996,10 +2005,10 @@ private:
|
||||
contextDescriptorAddress, contextDescriptor);
|
||||
|
||||
auto addParentNameAndRecurse =
|
||||
[&](uintptr_t parentContextDescriptorAddress,
|
||||
[&](remote::RemoteAddress parentContextDescriptorAddress,
|
||||
std::vector<ContextNameInfo> &chain) -> void {
|
||||
auto parentContextDescriptorBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(parentContextDescriptorAddress),
|
||||
parentContextDescriptorAddress,
|
||||
sizeof(ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
|
||||
if (!parentContextDescriptorBytes.get()) {
|
||||
Error = "Failed to read context descriptor.";
|
||||
@@ -2023,10 +2032,9 @@ private:
|
||||
// Set low bit indicates that this is an indirect reference
|
||||
if (parentDescriptorAddress & 0x1) {
|
||||
auto adjustedParentTargetAddress = parentDescriptorAddress & ~0x1;
|
||||
if (auto symbol = OpaquePointerReader(
|
||||
remote::RemoteAddress(adjustedParentTargetAddress),
|
||||
PointerSize)) {
|
||||
if (!symbol->getSymbol().empty()) {
|
||||
if (auto symbol =
|
||||
OpaquePointerReader(adjustedParentTargetAddress, PointerSize)) {
|
||||
if (!symbol->getSymbol().empty() && symbol->getOffset() == 0) {
|
||||
Demangle::Context Ctx;
|
||||
auto demangledRoot =
|
||||
Ctx.demangleSymbolAsNode(symbol->getSymbol().str());
|
||||
@@ -2071,8 +2079,9 @@ private:
|
||||
lastContext ? false : contextNameChain[i + 1].isAnonymous;
|
||||
if (nextContextIsAnonymous && !currentContextIsAnonymous) {
|
||||
std::stringstream stream;
|
||||
stream << "(" << contextNameInfo.name << " in $" << std::hex
|
||||
<< contextNameChain[i + 1].descriptorAddress << ")";
|
||||
stream << "(" << contextNameInfo.name << " in $"
|
||||
<< contextNameChain[i + 1].descriptorAddress.getDescription()
|
||||
<< ")";
|
||||
reversedQualifiedTypeNameMembers.push_back(stream.str());
|
||||
skipNext = true;
|
||||
} else if (nextContextIsAnonymous && currentContextIsAnonymous) {
|
||||
@@ -2103,11 +2112,11 @@ private:
|
||||
template <template <typename Runtime> class ObjCInteropKind,
|
||||
unsigned PointerSize>
|
||||
void extractOpaqueTypeProtocolRequirements(
|
||||
uintptr_t opaqueTypeDescriptorAddress,
|
||||
remote::RemoteAddress opaqueTypeDescriptorAddress,
|
||||
std::vector<std::string> &protocolRequirements,
|
||||
std::vector<TypeAliasInfo> &sameTypeRequirements) {
|
||||
auto opaqueTypeDescriptorBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(opaqueTypeDescriptorAddress),
|
||||
opaqueTypeDescriptorAddress,
|
||||
sizeof(ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
|
||||
if (!opaqueTypeDescriptorBytes.get()) {
|
||||
return;
|
||||
@@ -2125,16 +2134,15 @@ private:
|
||||
// is an offset to a TypeRef string, read it.
|
||||
auto readRequirementTypeRefAddress =
|
||||
[&](uintptr_t offsetFromOpaqueDescBase,
|
||||
uintptr_t requirementAddress) -> uintptr_t {
|
||||
uintptr_t requirementAddress) -> remote::RemoteAddress {
|
||||
std::string typeRefString = "";
|
||||
auto fieldOffsetOffset = requirementAddress + offsetFromOpaqueDescBase -
|
||||
(uintptr_t)opaqueTypeDescriptor;
|
||||
auto fieldOffsetAddress = opaqueTypeDescriptorAddress + fieldOffsetOffset;
|
||||
auto fieldOffsetBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(fieldOffsetAddress), sizeof(uint32_t));
|
||||
auto fieldOffsetBytes =
|
||||
OpaqueByteReader(fieldOffsetAddress, sizeof(uint32_t));
|
||||
auto fieldOffset = (const int32_t *)fieldOffsetBytes.get();
|
||||
auto fieldAddress = detail::applyRelativeOffset(
|
||||
(const char *)fieldOffsetAddress, *fieldOffset);
|
||||
auto fieldAddress = fieldOffsetAddress.applyRelativeOffset(*fieldOffset);
|
||||
return fieldAddress;
|
||||
};
|
||||
|
||||
@@ -2152,9 +2160,9 @@ private:
|
||||
|
||||
// Compute the address of the protocol descriptor by following the
|
||||
// offset
|
||||
auto protocolDescriptorAddress = detail::applyRelativeOffset(
|
||||
(const char *)protocolDescriptorOffsetAddress,
|
||||
protocolDescriptorOffsetValue);
|
||||
auto protocolDescriptorAddress =
|
||||
protocolDescriptorOffsetAddress.applyRelativeOffset(
|
||||
protocolDescriptorOffsetValue);
|
||||
|
||||
auto nameReader =
|
||||
QualifiedContextNameReader<ObjCInteropKind, PointerSize>(
|
||||
@@ -2219,7 +2227,7 @@ private:
|
||||
/// Extract conforming type's name from a Conformance Descriptor
|
||||
/// Returns a pair of (mangledTypeName, fullyQualifiedTypeName)
|
||||
std::optional<std::pair<std::string, std::string>> getConformingTypeName(
|
||||
const uintptr_t conformanceDescriptorAddress,
|
||||
const remote::RemoteAddress conformanceDescriptorAddress,
|
||||
const ExternalProtocolConformanceDescriptor<
|
||||
ObjCInteropKind, PointerSize> &conformanceDescriptor) {
|
||||
std::string typeName;
|
||||
@@ -2241,12 +2249,11 @@ private:
|
||||
// descriptor
|
||||
// - Address of the type descriptor is found at the (2) offset from the
|
||||
// conformance descriptor address
|
||||
auto contextDescriptorFieldAddress = detail::applyRelativeOffset(
|
||||
(const char *)conformanceDescriptorAddress,
|
||||
(int32_t)conformanceDescriptor.getTypeRefDescriptorOffset());
|
||||
auto contextDescriptorFieldAddress =
|
||||
conformanceDescriptorAddress.applyRelativeOffset(
|
||||
(int32_t)conformanceDescriptor.getTypeRefDescriptorOffset());
|
||||
auto contextDescriptorOffsetBytes =
|
||||
OpaqueByteReader(remote::RemoteAddress(contextDescriptorFieldAddress),
|
||||
sizeof(uint32_t));
|
||||
OpaqueByteReader(contextDescriptorFieldAddress, sizeof(uint32_t));
|
||||
if (!contextDescriptorOffsetBytes.get()) {
|
||||
Error =
|
||||
"Failed to read type descriptor field in conformance descriptor.";
|
||||
@@ -2256,15 +2263,15 @@ private:
|
||||
(const int32_t *)contextDescriptorOffsetBytes.get();
|
||||
|
||||
// Read the type descriptor itself using the address computed above
|
||||
auto contextTypeDescriptorAddress = detail::applyRelativeOffset(
|
||||
(const char *)contextDescriptorFieldAddress,
|
||||
*contextDescriptorOffset);
|
||||
auto contextTypeDescriptorAddress =
|
||||
contextDescriptorFieldAddress.applyRelativeOffset(
|
||||
*contextDescriptorOffset);
|
||||
|
||||
// Instead of a type descriptor this may just be a reference to an
|
||||
// external, check that first
|
||||
if (auto symbol = OpaqueDynamicSymbolResolver(
|
||||
remote::RemoteAddress(contextTypeDescriptorAddress))) {
|
||||
if (!symbol->isResolved()) {
|
||||
if (auto symbol =
|
||||
OpaqueDynamicSymbolResolver(contextTypeDescriptorAddress)) {
|
||||
if (!symbol->getSymbol().empty() && symbol->getOffset() == 0) {
|
||||
Demangle::Context Ctx;
|
||||
auto demangledRoot =
|
||||
Ctx.demangleSymbolAsNode(symbol->getSymbol().str());
|
||||
@@ -2283,10 +2290,10 @@ private:
|
||||
mangledTypeName = typeMangling.result();
|
||||
|
||||
return std::make_pair(mangledTypeName, typeName);
|
||||
} else if (symbol->getOffset()) {
|
||||
} else if (symbol->getResolvedAddress()) {
|
||||
// If symbol is empty and has an offset, this is the resolved remote
|
||||
// address
|
||||
contextTypeDescriptorAddress = symbol->getOffset();
|
||||
contextTypeDescriptorAddress = symbol->getResolvedAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2300,17 +2307,17 @@ private:
|
||||
|
||||
/// Extract protocol name from a Conformance Descriptor
|
||||
std::optional<std::string> getConformanceProtocolName(
|
||||
const uintptr_t conformanceDescriptorAddress,
|
||||
const remote::RemoteAddress conformanceDescriptorAddress,
|
||||
const ExternalProtocolConformanceDescriptor<
|
||||
ObjCInteropKind, PointerSize> &conformanceDescriptor) {
|
||||
std::optional<std::string> protocolName;
|
||||
auto protocolDescriptorFieldAddress = detail::applyRelativeOffset(
|
||||
(const char *)conformanceDescriptorAddress,
|
||||
(int32_t)conformanceDescriptor.getProtocolDescriptorOffset());
|
||||
auto protocolDescriptorFieldAddress =
|
||||
conformanceDescriptorAddress.applyRelativeOffset(
|
||||
|
||||
auto protocolDescriptorOffsetBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(protocolDescriptorFieldAddress),
|
||||
sizeof(uint32_t));
|
||||
(int32_t)conformanceDescriptor.getProtocolDescriptorOffset());
|
||||
|
||||
auto protocolDescriptorOffsetBytes =
|
||||
OpaqueByteReader(protocolDescriptorFieldAddress, sizeof(uint32_t));
|
||||
if (!protocolDescriptorOffsetBytes.get()) {
|
||||
Error = "Error reading protocol descriptor field in conformance "
|
||||
"descriptor.";
|
||||
@@ -2319,9 +2326,9 @@ private:
|
||||
auto protocolDescriptorOffset =
|
||||
(const uint32_t *)protocolDescriptorOffsetBytes.get();
|
||||
|
||||
auto protocolDescriptorTarget = detail::applyRelativeOffset(
|
||||
(const char *)protocolDescriptorFieldAddress,
|
||||
(int32_t)*protocolDescriptorOffset);
|
||||
auto protocolDescriptorTarget =
|
||||
protocolDescriptorFieldAddress.applyRelativeOffset(
|
||||
(int32_t)*protocolDescriptorOffset);
|
||||
|
||||
return NameReader.readFullyQualifiedProtocolName(
|
||||
protocolDescriptorTarget);
|
||||
@@ -2338,11 +2345,11 @@ private:
|
||||
*)conformanceRecordRef.getLocalBuffer();
|
||||
// Read the Protocol Conformance Descriptor by getting its address from
|
||||
// the conformance record.
|
||||
auto conformanceDescriptorAddress = (uintptr_t)CD->getRelative(
|
||||
(void *)conformanceRecordRef.getAddressData());
|
||||
auto conformanceDescriptorAddress =
|
||||
conformanceRecordRef.getRemoteAddress().getRelative(CD);
|
||||
|
||||
auto descriptorBytes = OpaqueByteReader(
|
||||
remote::RemoteAddress(conformanceDescriptorAddress),
|
||||
conformanceDescriptorAddress,
|
||||
sizeof(ExternalProtocolConformanceDescriptor<ObjCInteropKind,
|
||||
PointerSize>));
|
||||
if (!descriptorBytes.get()) {
|
||||
|
||||
@@ -754,6 +754,13 @@ public:
|
||||
SILType subst(SILModule &M, SubstitutionMap subs,
|
||||
TypeExpansionContext context) const;
|
||||
|
||||
/// Strip concurrency annotations from the representation type.
|
||||
SILType stripConcurrency(bool recursive, bool dropGlobalActor) {
|
||||
auto strippedASTTy = getASTType()->stripConcurrency(recursive, dropGlobalActor);
|
||||
return SILType::getPrimitiveType(strippedASTTy->getCanonicalType(),
|
||||
getCategory());
|
||||
}
|
||||
|
||||
/// Return true if this type references a "ref" type that has a single pointer
|
||||
/// representation. Class existentials do not always qualify.
|
||||
bool isHeapObjectReferenceType() const;
|
||||
|
||||
@@ -179,16 +179,16 @@ public:
|
||||
|
||||
void removeFlag(TrackableValueFlag flag) { flagSet -= flag; }
|
||||
|
||||
void print(llvm::raw_ostream &os) const {
|
||||
void print(SILFunction *fn, llvm::raw_ostream &os) const {
|
||||
os << "TrackableValueState[id: " << id
|
||||
<< "][is_no_alias: " << (isNoAlias() ? "yes" : "no")
|
||||
<< "][is_sendable: " << (isSendable() ? "yes" : "no")
|
||||
<< "][region_value_kind: ";
|
||||
getIsolationRegionInfo().printForOneLineLogging(os);
|
||||
getIsolationRegionInfo().printForOneLineLogging(fn, os);
|
||||
os << "].";
|
||||
}
|
||||
|
||||
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
|
||||
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) { print(fn, llvm::dbgs()); }
|
||||
|
||||
private:
|
||||
bool hasIsolationRegionInfo() const { return bool(regionInfo); }
|
||||
@@ -249,26 +249,26 @@ public:
|
||||
/// parameter.
|
||||
bool isSendingParameter() const;
|
||||
|
||||
void printIsolationInfo(SmallString<64> &outString) const {
|
||||
void printIsolationInfo(SILFunction *fn, SmallString<64> &outString) const {
|
||||
llvm::raw_svector_ostream os(outString);
|
||||
getIsolationRegionInfo().printForDiagnostics(os);
|
||||
getIsolationRegionInfo().printForDiagnostics(fn, os);
|
||||
}
|
||||
|
||||
void print(llvm::raw_ostream &os) const {
|
||||
void print(SILFunction *fn, llvm::raw_ostream &os) const {
|
||||
os << "TrackableValue. State: ";
|
||||
valueState.print(os);
|
||||
valueState.print(fn, os);
|
||||
os << "\n Rep Value: ";
|
||||
getRepresentative().print(os);
|
||||
}
|
||||
|
||||
void printVerbose(llvm::raw_ostream &os) const {
|
||||
void printVerbose(SILFunction *fn, llvm::raw_ostream &os) const {
|
||||
os << "TrackableValue. State: ";
|
||||
valueState.print(os);
|
||||
valueState.print(fn, os);
|
||||
os << "\n Rep Value: " << getRepresentative();
|
||||
}
|
||||
|
||||
SWIFT_DEBUG_DUMP {
|
||||
print(llvm::dbgs());
|
||||
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) {
|
||||
print(fn, llvm::dbgs());
|
||||
llvm::dbgs() << '\n';
|
||||
}
|
||||
};
|
||||
@@ -288,8 +288,8 @@ struct regionanalysisimpl::TrackableValueLookupResult {
|
||||
/// TrackableValue.
|
||||
std::optional<TrackableValue> base;
|
||||
|
||||
void print(llvm::raw_ostream &os) const;
|
||||
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
|
||||
void print(SILFunction *fn, llvm::raw_ostream &os) const;
|
||||
SWIFT_DEBUG_DUMPER(dumper(SILFunction *fn)) { print(fn, llvm::dbgs()); }
|
||||
};
|
||||
|
||||
class RegionAnalysis;
|
||||
@@ -390,6 +390,8 @@ public:
|
||||
return getUnderlyingTrackedValue(value).value;
|
||||
}
|
||||
|
||||
SILFunction *getFunction() const { return fn; }
|
||||
|
||||
/// Returns the value for this instruction if it isn't a fake "represenative
|
||||
/// value" to inject actor isolatedness. Asserts in such a case.
|
||||
SILValue getRepresentative(Element trackableValueID) const;
|
||||
|
||||
@@ -367,6 +367,8 @@ struct BridgedPassContext {
|
||||
BRIDGED_INLINE void SSAUpdater_addAvailableValue(BridgedBasicBlock block, BridgedValue value) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedValue SSAUpdater_getValueAtEndOfBlock(BridgedBasicBlock block) const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedValue SSAUpdater_getValueInMiddleOfBlock(BridgedBasicBlock block) const;
|
||||
BRIDGED_INLINE SwiftInt SSAUpdater_getNumInsertedPhis() const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedValue SSAUpdater_getInsertedPhi(SwiftInt idx) const;
|
||||
|
||||
// Options
|
||||
|
||||
|
||||
@@ -548,6 +548,14 @@ BridgedValue BridgedPassContext::SSAUpdater_getValueInMiddleOfBlock(BridgedBasic
|
||||
invocation->getSSAUpdater()->getValueInMiddleOfBlock(block.unbridged())};
|
||||
}
|
||||
|
||||
SwiftInt BridgedPassContext::SSAUpdater_getNumInsertedPhis() const {
|
||||
return (SwiftInt)invocation->getInsertedPhisBySSAUpdater().size();
|
||||
}
|
||||
|
||||
BridgedValue BridgedPassContext::SSAUpdater_getInsertedPhi(SwiftInt idx) const {
|
||||
return {invocation->getInsertedPhisBySSAUpdater()[idx]};
|
||||
}
|
||||
|
||||
bool BridgedPassContext::enableStackProtection() const {
|
||||
swift::SILModule *mod = invocation->getPassManager()->getModule();
|
||||
return mod->getOptions().EnableStackProtection;
|
||||
|
||||
@@ -75,6 +75,7 @@ class SwiftPassInvocation {
|
||||
SILModule::SlabList allocatedSlabs;
|
||||
|
||||
SILSSAUpdater *ssaUpdater = nullptr;
|
||||
SmallVector<SILPhiArgument *, 4> insertedPhisBySSAUpdater;
|
||||
|
||||
SwiftPassInvocation *nestedSwiftPassInvocation = nullptr;
|
||||
|
||||
@@ -178,8 +179,9 @@ public:
|
||||
|
||||
void initializeSSAUpdater(SILFunction *fn, SILType type,
|
||||
ValueOwnershipKind ownership) {
|
||||
insertedPhisBySSAUpdater.clear();
|
||||
if (!ssaUpdater)
|
||||
ssaUpdater = new SILSSAUpdater;
|
||||
ssaUpdater = new SILSSAUpdater(&insertedPhisBySSAUpdater);
|
||||
ssaUpdater->initialize(fn, type, ownership);
|
||||
}
|
||||
|
||||
@@ -188,6 +190,8 @@ public:
|
||||
return ssaUpdater;
|
||||
}
|
||||
|
||||
ArrayRef<SILPhiArgument *> getInsertedPhisBySSAUpdater() { return insertedPhisBySSAUpdater; }
|
||||
|
||||
SwiftPassInvocation *initializeNestedSwiftPassInvocation(SILFunction *newFunction) {
|
||||
assert(!nestedSwiftPassInvocation && "Nested Swift pass invocation already initialized");
|
||||
nestedSwiftPassInvocation = new SwiftPassInvocation(passManager, transform, newFunction);
|
||||
|
||||
@@ -76,7 +76,7 @@ bool canDevirtualizeClassMethod(FullApplySite AI, ClassDecl *CD,
|
||||
CanType ClassType,
|
||||
OptRemark::Emitter *ORE = nullptr,
|
||||
bool isEffectivelyFinalMethod = false);
|
||||
SILFunction *getTargetClassMethod(SILModule &M, ClassDecl *CD,
|
||||
SILFunction *getTargetClassMethod(SILModule &M, FullApplySite as, ClassDecl *CD,
|
||||
CanType ClassType, MethodInst *MI);
|
||||
CanType getSelfInstanceType(CanType ClassOrMetatypeType);
|
||||
|
||||
|
||||
@@ -1598,9 +1598,32 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool isConvertFunctionFromSendableType(SILValue equivalenceClassRep) const {
|
||||
/// To work around not having isolation in interface types, the type checker
|
||||
/// inserts casts and other AST nodes that are used to enrich the AST with
|
||||
/// isolation information. This results in Sendable functions being
|
||||
/// wrapped/converted/etc in ways that hide the Sendability. This helper looks
|
||||
/// through these conversions/wrappers/thunks to see if the original
|
||||
/// underlying function is Sendable.
|
||||
///
|
||||
/// The two ways this can happen is that we either get an actual function_ref
|
||||
/// that is Sendable or we get a convert function with a Sendable operand.
|
||||
bool isHiddenSendableFunctionType(SILValue equivalenceClassRep) const {
|
||||
SILValue valueToTest = equivalenceClassRep;
|
||||
while (true) {
|
||||
if (auto *pai = dyn_cast<PartialApplyInst>(valueToTest)) {
|
||||
if (auto *calleeFunction = pai->getCalleeFunction()) {
|
||||
if (pai->getNumArguments() >= 1 &&
|
||||
pai->getArgument(0)->getType().isFunction() &&
|
||||
calleeFunction->isThunk()) {
|
||||
valueToTest = pai->getArgument(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (calleeFunction->getLoweredFunctionType()->isSendable())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *i = dyn_cast<ThinToThickFunctionInst>(valueToTest)) {
|
||||
valueToTest = i->getOperand();
|
||||
continue;
|
||||
@@ -1612,6 +1635,9 @@ private:
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto *fn = dyn_cast<FunctionRefInst>(valueToTest))
|
||||
return fn->getReferencedFunction()->getLoweredFunctionType()->isSendable();
|
||||
|
||||
auto *cvi = dyn_cast<ConvertFunctionInst>(valueToTest);
|
||||
if (!cvi)
|
||||
return false;
|
||||
@@ -1644,7 +1670,7 @@ private:
|
||||
|
||||
// See if we have a convert function from a `@Sendable` type. In this
|
||||
// case, we want to squelch the error.
|
||||
if (isConvertFunctionFromSendableType(equivalenceClassRep))
|
||||
if (isHiddenSendableFunctionType(equivalenceClassRep))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1689,7 +1715,7 @@ private:
|
||||
|
||||
// See if we have a convert function from a `@Sendable` type. In this
|
||||
// case, we want to squelch the error.
|
||||
if (isConvertFunctionFromSendableType(equivalenceClassRep))
|
||||
if (isHiddenSendableFunctionType(equivalenceClassRep))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,8 +185,12 @@ public:
|
||||
/// parameter and should be allowed to merge into a self parameter.
|
||||
UnappliedIsolatedAnyParameter = 0x2,
|
||||
|
||||
/// If set, this was a TaskIsolated value from a nonisolated(nonsending)
|
||||
/// parameter.
|
||||
NonisolatedNonsendingTaskIsolated = 0x4,
|
||||
|
||||
/// The maximum number of bits used by a Flag.
|
||||
MaxNumBits = 2,
|
||||
MaxNumBits = 3,
|
||||
};
|
||||
|
||||
using Options = OptionSet<Flag>;
|
||||
@@ -204,13 +208,19 @@ private:
|
||||
/// derived isolatedValue from.
|
||||
ActorInstance actorInstance;
|
||||
|
||||
/// When the isolation is introduced due to a (potentially) isolated
|
||||
/// conformance, the protocol whose conformance might be isolated.
|
||||
ProtocolDecl *isolatedConformance = nullptr;
|
||||
|
||||
unsigned kind : 8;
|
||||
unsigned options : 8;
|
||||
|
||||
SILIsolationInfo(SILValue isolatedValue, SILValue actorInstance,
|
||||
ActorIsolation actorIsolation, Options options = Options())
|
||||
ActorIsolation actorIsolation, Options options = Options(),
|
||||
ProtocolDecl *isolatedConformance = nullptr)
|
||||
: actorIsolation(actorIsolation), isolatedValue(isolatedValue),
|
||||
actorInstance(ActorInstance::getForValue(actorInstance)), kind(Actor),
|
||||
actorInstance(ActorInstance::getForValue(actorInstance)),
|
||||
isolatedConformance(isolatedConformance), kind(Actor),
|
||||
options(options.toRaw()) {
|
||||
assert((!actorInstance ||
|
||||
(actorIsolation.getKind() == ActorIsolation::ActorInstance &&
|
||||
@@ -219,23 +229,39 @@ private:
|
||||
->lookThroughAllOptionalTypes()
|
||||
->getAnyActor())) &&
|
||||
"actorInstance must be an actor if it is non-empty");
|
||||
assert((getKind() != Disconnected || isolatedConformance == nullptr) &&
|
||||
"isolated conformance cannot be introduced with disconnected region");
|
||||
}
|
||||
|
||||
SILIsolationInfo(SILValue isolatedValue, ActorInstance actorInstance,
|
||||
ActorIsolation actorIsolation, Options options = Options())
|
||||
ActorIsolation actorIsolation, Options options = Options(),
|
||||
ProtocolDecl *isolatedConformance = nullptr)
|
||||
: actorIsolation(actorIsolation), isolatedValue(isolatedValue),
|
||||
actorInstance(actorInstance), kind(Actor), options(options.toRaw()) {
|
||||
actorInstance(actorInstance), isolatedConformance(isolatedConformance),
|
||||
kind(Actor), options(options.toRaw())
|
||||
{
|
||||
assert(actorInstance);
|
||||
assert(actorIsolation.getKind() == ActorIsolation::ActorInstance);
|
||||
}
|
||||
|
||||
SILIsolationInfo(Kind kind, SILValue isolatedValue)
|
||||
: actorIsolation(), isolatedValue(isolatedValue), kind(kind), options(0) {
|
||||
SILIsolationInfo(Kind kind, SILValue isolatedValue,
|
||||
ProtocolDecl *isolatedConformance = nullptr)
|
||||
: actorIsolation(), isolatedValue(isolatedValue),
|
||||
isolatedConformance(isolatedConformance), kind(kind), options(0) {
|
||||
}
|
||||
|
||||
SILIsolationInfo(Kind kind, Options options = Options())
|
||||
: actorIsolation(), kind(kind), options(options.toRaw()) {}
|
||||
|
||||
/// Infer isolation region from the set of protocol conformances.
|
||||
static SILIsolationInfo getFromConformances(
|
||||
SILValue value, ArrayRef<ProtocolConformanceRef> conformances);
|
||||
|
||||
/// Determine the isolation of conformances that could be introduced by a
|
||||
/// cast from sourceType to destType.
|
||||
static SILIsolationInfo getForCastConformances(
|
||||
SILValue value, CanType sourceType, CanType destType);
|
||||
|
||||
public:
|
||||
SILIsolationInfo() : actorIsolation(), kind(Kind::Unknown), options(0) {}
|
||||
|
||||
@@ -257,6 +283,12 @@ public:
|
||||
return getOptions().contains(Flag::UnsafeNonIsolated);
|
||||
}
|
||||
|
||||
// Retrieve the protocol to which there is (or could be) an isolated
|
||||
// conformance.
|
||||
ProtocolDecl *getIsolatedConformance() const {
|
||||
return isolatedConformance;
|
||||
}
|
||||
|
||||
SILIsolationInfo withUnsafeNonIsolated(bool newValue = true) const {
|
||||
assert(*this && "Cannot be unknown");
|
||||
auto self = *this;
|
||||
@@ -269,6 +301,45 @@ public:
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Produce a new isolation info value that merges in the given isolated
|
||||
/// conformance value.
|
||||
///
|
||||
/// If both isolation infos have an isolation conformance, pick one
|
||||
/// arbitrarily. Otherwise, the result has no isolated conformance.
|
||||
SILIsolationInfo
|
||||
withMergedIsolatedConformance(ProtocolDecl *newIsolatedConformance) const {
|
||||
SILIsolationInfo result(*this);
|
||||
if (!isolatedConformance || !newIsolatedConformance) {
|
||||
result.isolatedConformance = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.isolatedConformance =
|
||||
ProtocolDecl::compare(isolatedConformance, newIsolatedConformance) <= 0
|
||||
? isolatedConformance
|
||||
: newIsolatedConformance;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isNonisolatedNonsendingTaskIsolated() const {
|
||||
return getOptions().contains(Flag::NonisolatedNonsendingTaskIsolated);
|
||||
}
|
||||
|
||||
SILIsolationInfo
|
||||
withNonisolatedNonsendingTaskIsolated(bool newValue = true) const {
|
||||
assert(*this && "Cannot be unknown");
|
||||
assert(isTaskIsolated() && "Can only be task isolated");
|
||||
auto self = *this;
|
||||
if (newValue) {
|
||||
self.options =
|
||||
(self.getOptions() | Flag::NonisolatedNonsendingTaskIsolated).toRaw();
|
||||
} else {
|
||||
self.options = self.getOptions().toRaw() &
|
||||
~Options(Flag::NonisolatedNonsendingTaskIsolated).toRaw();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Returns true if this actor isolation is derived from an unapplied
|
||||
/// isolation parameter. When merging, we allow for this to be merged with a
|
||||
/// more specific isolation kind.
|
||||
@@ -289,16 +360,16 @@ public:
|
||||
return self;
|
||||
}
|
||||
|
||||
void print(llvm::raw_ostream &os) const;
|
||||
void print(SILFunction *fn, llvm::raw_ostream &os) const;
|
||||
|
||||
/// Print a textual representation of the text info that is meant to be
|
||||
/// included in other logging output for types that compose with
|
||||
/// SILIsolationInfo. As a result, we only print state that can fit on
|
||||
/// one line.
|
||||
void printForOneLineLogging(llvm::raw_ostream &os) const;
|
||||
void printForOneLineLogging(SILFunction *fn, llvm::raw_ostream &os) const;
|
||||
|
||||
SWIFT_DEBUG_DUMP {
|
||||
print(llvm::dbgs());
|
||||
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) {
|
||||
print(fn, llvm::dbgs());
|
||||
llvm::dbgs() << '\n';
|
||||
}
|
||||
|
||||
@@ -307,12 +378,20 @@ public:
|
||||
///
|
||||
/// We do this programatically since task-isolated code needs a very different
|
||||
/// form of diagnostic than other cases.
|
||||
void printForCodeDiagnostic(llvm::raw_ostream &os) const;
|
||||
void printForCodeDiagnostic(SILFunction *fn, llvm::raw_ostream &os) const;
|
||||
|
||||
void printForDiagnostics(llvm::raw_ostream &os) const;
|
||||
/// Overload of printForCodeDiagnostics that returns an interned StringRef
|
||||
/// owned by the AST.
|
||||
StringRef printForCodeDiagnostic(SILFunction *fn) const;
|
||||
|
||||
SWIFT_DEBUG_DUMPER(dumpForDiagnostics()) {
|
||||
printForDiagnostics(llvm::dbgs());
|
||||
void printForDiagnostics(SILFunction *fn, llvm::raw_ostream &os) const;
|
||||
|
||||
/// Overload of printForDiagnostics that returns an interned StringRef owned
|
||||
/// by the AST.
|
||||
StringRef printForDiagnostics(SILFunction *fn) const;
|
||||
|
||||
SWIFT_DEBUG_DUMPER(dumpForDiagnostics(SILFunction *fn)) {
|
||||
printForDiagnostics(fn, llvm::dbgs());
|
||||
llvm::dbgs() << '\n';
|
||||
}
|
||||
|
||||
@@ -427,10 +506,13 @@ public:
|
||||
Flag::UnappliedIsolatedAnyParameter};
|
||||
}
|
||||
|
||||
static SILIsolationInfo getGlobalActorIsolated(SILValue value,
|
||||
Type globalActorType) {
|
||||
static SILIsolationInfo getGlobalActorIsolated(
|
||||
SILValue value,
|
||||
Type globalActorType,
|
||||
ProtocolDecl *isolatedConformance = nullptr) {
|
||||
return {value, SILValue() /*no actor instance*/,
|
||||
ActorIsolation::forGlobalActor(globalActorType)};
|
||||
ActorIsolation::forGlobalActor(globalActorType),
|
||||
Options(), isolatedConformance};
|
||||
}
|
||||
|
||||
static SILIsolationInfo getGlobalActorIsolated(SILValue value,
|
||||
@@ -442,8 +524,9 @@ public:
|
||||
isolation.getGlobalActor());
|
||||
}
|
||||
|
||||
static SILIsolationInfo getTaskIsolated(SILValue value) {
|
||||
return {Kind::Task, value};
|
||||
static SILIsolationInfo getTaskIsolated(
|
||||
SILValue value, ProtocolDecl *isolatedConformance = nullptr) {
|
||||
return {Kind::Task, value, isolatedConformance};
|
||||
}
|
||||
|
||||
/// Attempt to infer the isolation region info for \p inst.
|
||||
@@ -460,6 +543,9 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
/// Infer isolation of conformances for the given instruction.
|
||||
static SILIsolationInfo getConformanceIsolation(SILInstruction *inst);
|
||||
|
||||
/// A helper that is used to ensure that we treat certain builtin values as
|
||||
/// non-Sendable that the AST level otherwise thinks are non-Sendable.
|
||||
///
|
||||
@@ -494,6 +580,19 @@ public:
|
||||
/// that the isolation and the isolated value match.
|
||||
bool isEqual(const SILIsolationInfo &other) const;
|
||||
|
||||
/// A helper function that prints ActorIsolation like we normally do except
|
||||
/// that it prints nonisolated(nonsending) as nonisolated. This is needed in
|
||||
/// certain cases when talking about use-after-free uses in send non sendable.
|
||||
static void printActorIsolationForDiagnostics(
|
||||
SILFunction *fn, ActorIsolation iso, llvm::raw_ostream &os,
|
||||
StringRef openingQuotationMark = "'", bool asNoun = false);
|
||||
|
||||
/// Overload for printActorIsolationForDiagnostics that produces a StringRef.
|
||||
static StringRef
|
||||
printActorIsolationForDiagnostics(SILFunction *fn, ActorIsolation iso,
|
||||
StringRef openingQuotationMark = "'",
|
||||
bool asNoun = false);
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &id) const;
|
||||
|
||||
private:
|
||||
@@ -557,43 +656,33 @@ public:
|
||||
SILIsolationInfo::getDisconnected(isUnsafeNonIsolated));
|
||||
}
|
||||
|
||||
SWIFT_DEBUG_DUMP { innerInfo.dump(); }
|
||||
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) { innerInfo.dump(fn); }
|
||||
|
||||
void printForDiagnostics(llvm::raw_ostream &os) const {
|
||||
innerInfo.printForDiagnostics(os);
|
||||
void printForDiagnostics(SILFunction *fn, llvm::raw_ostream &os) const {
|
||||
innerInfo.printForDiagnostics(fn, os);
|
||||
}
|
||||
|
||||
SWIFT_DEBUG_DUMPER(dumpForDiagnostics()) {
|
||||
innerInfo.dumpForDiagnostics();
|
||||
StringRef printForDiagnostics(SILFunction *fn) const {
|
||||
return innerInfo.printForDiagnostics(fn);
|
||||
}
|
||||
|
||||
void printForCodeDiagnostic(llvm::raw_ostream &os) const {
|
||||
innerInfo.printForCodeDiagnostic(os);
|
||||
SWIFT_DEBUG_DUMPER(dumpForDiagnostics(SILFunction *fn)) {
|
||||
innerInfo.dumpForDiagnostics(fn);
|
||||
}
|
||||
|
||||
void printForOneLineLogging(llvm::raw_ostream &os) const {
|
||||
innerInfo.printForOneLineLogging(os);
|
||||
void printForCodeDiagnostic(SILFunction *fn, llvm::raw_ostream &os) const {
|
||||
innerInfo.printForCodeDiagnostic(fn, os);
|
||||
}
|
||||
|
||||
StringRef printForCodeDiagnostic(SILFunction *fn) const {
|
||||
return innerInfo.printForCodeDiagnostic(fn);
|
||||
}
|
||||
|
||||
void printForOneLineLogging(SILFunction *fn, llvm::raw_ostream &os) const {
|
||||
innerInfo.printForOneLineLogging(fn, os);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace swift
|
||||
|
||||
namespace llvm {
|
||||
|
||||
inline llvm::raw_ostream &
|
||||
operator<<(llvm::raw_ostream &os,
|
||||
const swift::SILIsolationInfo &isolationInfo) {
|
||||
isolationInfo.printForOneLineLogging(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
inline llvm::raw_ostream &
|
||||
operator<<(llvm::raw_ostream &os,
|
||||
const swift::SILDynamicMergedIsolationInfo &isolationInfo) {
|
||||
isolationInfo.printForOneLineLogging(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
@@ -170,8 +170,7 @@ protected:
|
||||
bool isTestableImport, bool isCandidateForTextualModule);
|
||||
|
||||
struct BinaryModuleImports {
|
||||
llvm::StringSet<> moduleImports;
|
||||
llvm::StringSet<> exportedModules;
|
||||
std::vector<ScannerImportStatementInfo> moduleImports;
|
||||
std::string headerImport;
|
||||
};
|
||||
|
||||
|
||||
@@ -39,8 +39,12 @@ private:
|
||||
uint64_t HeaderAddress;
|
||||
std::vector<Segment> Segments;
|
||||
struct DynamicRelocation {
|
||||
/// The symbol name that the pointer refers to. Empty if only an absolute
|
||||
/// address is available.
|
||||
StringRef Symbol;
|
||||
uint64_t Offset;
|
||||
// The offset (if the symbol is available), or the resolved remote address
|
||||
// if the symbol is empty.
|
||||
uint64_t OffsetOrAddress;
|
||||
};
|
||||
llvm::DenseMap<uint64_t, DynamicRelocation> DynamicRelocations;
|
||||
|
||||
@@ -88,14 +92,19 @@ class ObjectMemoryReader : public reflection::MemoryReader {
|
||||
};
|
||||
std::vector<ImageEntry> Images;
|
||||
|
||||
uint64_t PtrauthMask = 0;
|
||||
|
||||
std::pair<const Image *, uint64_t>
|
||||
decodeImageIndexAndAddress(uint64_t Addr) const;
|
||||
|
||||
uint64_t encodeImageIndexAndAddress(const Image *image,
|
||||
uint64_t imageAddr) const;
|
||||
remote::RemoteAddress
|
||||
encodeImageIndexAndAddress(const Image *image,
|
||||
remote::RemoteAddress imageAddr) const;
|
||||
|
||||
StringRef getContentsAtAddress(uint64_t Addr, uint64_t Size);
|
||||
|
||||
uint64_t getPtrauthMask();
|
||||
|
||||
public:
|
||||
explicit ObjectMemoryReader(
|
||||
const std::vector<const llvm::object::ObjectFile *> &ObjectFiles);
|
||||
@@ -110,7 +119,7 @@ public:
|
||||
// TODO: We could consult the dynamic symbol tables of the images to
|
||||
// implement this.
|
||||
reflection::RemoteAddress getSymbolAddress(const std::string &name) override {
|
||||
return reflection::RemoteAddress(nullptr);
|
||||
return reflection::RemoteAddress();
|
||||
}
|
||||
|
||||
ReadBytesResult readBytes(reflection::RemoteAddress Addr,
|
||||
|
||||
Reference in New Issue
Block a user