Merge branch 'release/6.2' into cdecl-6.2

This commit is contained in:
Xi Ge
2025-07-15 14:50:10 -07:00
committed by GitHub
307 changed files with 7168 additions and 4097 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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.

View File

@@ -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 *))

View File

@@ -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

View File

@@ -230,7 +230,7 @@ public:
private:
bool isOperatorSlow() const;
};
class DeclName;
class DeclNameRef;
class ObjCSelector;

View File

@@ -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());

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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

View File

@@ -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>;

View File

@@ -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

View File

@@ -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];

View File

@@ -105,8 +105,8 @@ class InProcessMemoryReader final : public MemoryReader {
return ReadBytesResult(address.getLocalPointer<void>(), [](const void *) {});
}
};
}
}
} // namespace remote
} // namespace swift
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
};

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -170,8 +170,7 @@ protected:
bool isTestableImport, bool isCandidateForTextualModule);
struct BinaryModuleImports {
llvm::StringSet<> moduleImports;
llvm::StringSet<> exportedModules;
std::vector<ScannerImportStatementInfo> moduleImports;
std::string headerImport;
};

View File

@@ -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,