mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The annotation must precede the declaration to which it appertains during the definition. The re-ordering was silently accepted by clang but is not correct as per the GNU style. This was flagged by GCC 7.
228 lines
7.1 KiB
C++
228 lines
7.1 KiB
C++
//===--- swift-remoteast-test.cpp - RemoteAST testing application ---------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// This file supports performing target-specific remote reflection tests
|
|
// on live swift executables.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/RemoteAST/RemoteAST.h"
|
|
#include "swift/Remote/InProcessMemoryReader.h"
|
|
#include "swift/Remote/MetadataReader.h"
|
|
#include "swift/Runtime/Metadata.h"
|
|
#include "swift/Frontend/Frontend.h"
|
|
#include "swift/FrontendTool/FrontendTool.h"
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/Basic/LLVMInitialize.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Support/Format.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <cassert>
|
|
|
|
#if defined(__ELF__)
|
|
#define SWIFT_REMOTEAST_TEST_ABI __attribute__((__visibility__("default")))
|
|
#elif defined(__MACH__)
|
|
#define SWIFT_REMOTEAST_TEST_ABI __attribute__((__visibility__("default")))
|
|
#else
|
|
#define SWIFT_REMOTEAST_TEST_ABI __declspec(dllexport)
|
|
#endif
|
|
|
|
using namespace swift;
|
|
using namespace swift::remote;
|
|
using namespace swift::remoteAST;
|
|
|
|
#if defined(__APPLE__) && defined(__MACH__)
|
|
#include <dlfcn.h>
|
|
static unsigned long long computeClassIsSwiftMask(void) {
|
|
uintptr_t *objc_debug_swift_stable_abi_bit_ptr =
|
|
(uintptr_t *)dlsym(RTLD_DEFAULT, "objc_debug_swift_stable_abi_bit");
|
|
return objc_debug_swift_stable_abi_bit_ptr ?
|
|
*objc_debug_swift_stable_abi_bit_ptr : 1;
|
|
}
|
|
#else
|
|
static unsigned long long computeClassIsSwiftMask(void) {
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
extern "C" unsigned long long _swift_classIsSwiftMask =
|
|
computeClassIsSwiftMask();
|
|
|
|
/// The context for the code we're running. Set by the observer.
|
|
static ASTContext *context = nullptr;
|
|
|
|
/// The RemoteAST for the code we're running.
|
|
std::unique_ptr<RemoteASTContext> remoteContext;
|
|
|
|
static RemoteASTContext &getRemoteASTContext() {
|
|
if (remoteContext)
|
|
return *remoteContext;
|
|
|
|
std::shared_ptr<MemoryReader> reader(new InProcessMemoryReader());
|
|
remoteContext.reset(new RemoteASTContext(*context, std::move(reader)));
|
|
return *remoteContext;
|
|
}
|
|
|
|
// FIXME: swiftcall
|
|
/// func printType(forMetadata: Any.Type)
|
|
extern "C" void SWIFT_REMOTEAST_TEST_ABI LLVM_ATTRIBUTE_USED
|
|
printMetadataType(const Metadata *typeMetadata) {
|
|
auto &remoteAST = getRemoteASTContext();
|
|
auto &out = llvm::outs();
|
|
|
|
auto result =
|
|
remoteAST.getTypeForRemoteTypeMetadata(RemoteAddress(typeMetadata));
|
|
if (result) {
|
|
out << "found type: ";
|
|
result.getValue().print(out);
|
|
out << '\n';
|
|
} else {
|
|
out << result.getFailure().render() << '\n';
|
|
}
|
|
}
|
|
|
|
// FIXME: swiftcall
|
|
/// func printDynamicType(_: AnyObject)
|
|
extern "C" void SWIFT_REMOTEAST_TEST_ABI LLVM_ATTRIBUTE_USED
|
|
printHeapMetadataType(void *object) {
|
|
auto &remoteAST = getRemoteASTContext();
|
|
auto &out = llvm::outs();
|
|
|
|
auto metadataResult =
|
|
remoteAST.getHeapMetadataForObject(RemoteAddress(object));
|
|
if (!metadataResult) {
|
|
out << metadataResult.getFailure().render() << '\n';
|
|
return;
|
|
}
|
|
auto metadata = metadataResult.getValue();
|
|
|
|
auto result =
|
|
remoteAST.getTypeForRemoteTypeMetadata(metadata, /*skipArtificial*/ true);
|
|
if (result) {
|
|
out << "found type: ";
|
|
result.getValue().print(out);
|
|
out << '\n';
|
|
} else {
|
|
out << result.getFailure().render() << '\n';
|
|
}
|
|
}
|
|
|
|
static void printMemberOffset(const Metadata *typeMetadata,
|
|
StringRef memberName, bool passMetadata) {
|
|
auto &remoteAST = getRemoteASTContext();
|
|
auto &out = llvm::outs();
|
|
|
|
// The first thing we have to do is get the type.
|
|
auto typeResult =
|
|
remoteAST.getTypeForRemoteTypeMetadata(RemoteAddress(typeMetadata));
|
|
if (!typeResult) {
|
|
out << "failed to find type: " << typeResult.getFailure().render() << '\n';
|
|
return;
|
|
}
|
|
|
|
Type type = typeResult.getValue();
|
|
|
|
RemoteAddress address =
|
|
(passMetadata ? RemoteAddress(typeMetadata) : RemoteAddress(nullptr));
|
|
|
|
auto offsetResult =
|
|
remoteAST.getOffsetOfMember(type, address, memberName);
|
|
if (!offsetResult) {
|
|
out << "failed to find offset: "
|
|
<< offsetResult.getFailure().render() << '\n';
|
|
return;
|
|
}
|
|
|
|
out << "found offset: " << offsetResult.getValue() << '\n';
|
|
}
|
|
|
|
// FIXME: swiftcall
|
|
/// func printTypeMemberOffset(forType: Any.Type, memberName: StaticString)
|
|
extern "C" void SWIFT_REMOTEAST_TEST_ABI LLVM_ATTRIBUTE_USED
|
|
printTypeMemberOffset(const Metadata *typeMetadata,
|
|
const char *memberName) {
|
|
printMemberOffset(typeMetadata, memberName, /*pass metadata*/ false);
|
|
}
|
|
|
|
// FIXME: swiftcall
|
|
/// func printTypeMetadataMemberOffset(forType: Any.Type,
|
|
/// memberName: StaticString)
|
|
extern "C" void SWIFT_REMOTEAST_TEST_ABI LLVM_ATTRIBUTE_USED
|
|
printTypeMetadataMemberOffset(const Metadata *typeMetadata,
|
|
const char *memberName) {
|
|
printMemberOffset(typeMetadata, memberName, /*pass metadata*/ true);
|
|
}
|
|
|
|
// FIXME: swiftcall
|
|
/// func printDynamicTypeAndAddressForExistential<T>(_: T)
|
|
extern "C" void SWIFT_REMOTEAST_TEST_ABI LLVM_ATTRIBUTE_USED
|
|
printDynamicTypeAndAddressForExistential(void *object,
|
|
const Metadata *typeMetadata) {
|
|
auto &remoteAST = getRemoteASTContext();
|
|
auto &out = llvm::outs();
|
|
|
|
// First, retrieve the static type of the existential, so we can understand
|
|
// which kind of existential this is.
|
|
auto staticTypeResult =
|
|
remoteAST.getTypeForRemoteTypeMetadata(RemoteAddress(typeMetadata));
|
|
if (!staticTypeResult) {
|
|
out << "failed to resolve static type: "
|
|
<< staticTypeResult.getFailure().render() << '\n';
|
|
return;
|
|
}
|
|
|
|
// OK, we can reconstruct the dynamic type and the address now.
|
|
auto result = remoteAST.getDynamicTypeAndAddressForExistential(
|
|
RemoteAddress(object), staticTypeResult.getValue());
|
|
if (result) {
|
|
out << "found type: ";
|
|
result.getValue().InstanceType.print(out);
|
|
out << "\n";
|
|
} else {
|
|
out << result.getFailure().render() << '\n';
|
|
}
|
|
}
|
|
|
|
// FIXME: swiftcall
|
|
/// func stopRemoteAST(_: AnyObject)
|
|
extern "C" void SWIFT_REMOTEAST_TEST_ABI LLVM_ATTRIBUTE_USED
|
|
stopRemoteAST() {
|
|
if (remoteContext)
|
|
remoteContext.reset();
|
|
}
|
|
|
|
namespace {
|
|
|
|
struct Observer : public FrontendObserver {
|
|
void configuredCompiler(CompilerInstance &instance) override {
|
|
context = &instance.getASTContext();
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
int main(int argc, const char *argv[]) {
|
|
PROGRAM_START(argc, argv);
|
|
|
|
unsigned numForwardedArgs = argc
|
|
- 1 // we drop argv[0]
|
|
+ 1; // -interpret
|
|
|
|
SmallVector<const char *, 8> forwardedArgs;
|
|
forwardedArgs.reserve(numForwardedArgs);
|
|
forwardedArgs.append(&argv[1], &argv[argc]);
|
|
forwardedArgs.push_back("-interpret");
|
|
assert(forwardedArgs.size() == numForwardedArgs);
|
|
|
|
Observer observer;
|
|
return performFrontend(forwardedArgs, argv[0], (void*) &printMetadataType,
|
|
&observer);
|
|
}
|