Skip to content

Commit 7816513

Browse files
committed
Swift SIL: add bridging for vTables
1 parent 87f2f41 commit 7816513

File tree

8 files changed

+144
-5
lines changed

8 files changed

+144
-5
lines changed

SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import OptimizerBridging
1515

1616
/// The context which is passed to a `ModulePass`'s run-function.
1717
///
18-
/// It provides access to all functions of a module, but it doesn't provide any
19-
/// APIs to modify functions.
18+
/// It provides access to all functions, v-tables and witness tables of a module,
19+
/// but it doesn't provide any APIs to modify functions.
2020
/// In order to modify a function, a module pass must use `transform(function:)`.
2121
struct ModulePassContext {
2222
let _bridged: BridgedPassContext
@@ -34,11 +34,27 @@ struct ModulePassContext {
3434
return nil
3535
}
3636
}
37-
37+
38+
struct VTableArray : BridgedRandomAccessCollection {
39+
fileprivate let bridged: BridgedVTableArray
40+
41+
var startIndex: Int { return 0 }
42+
var endIndex: Int { return Int(bridged.count) }
43+
44+
subscript(_ index: Int) -> VTable {
45+
precondition(index >= 0 && index < bridged.count)
46+
return VTable(bridged: bridged.vTables![index])
47+
}
48+
}
49+
3850
var functions: FunctionList {
3951
FunctionList(first: PassContext_firstFunctionInModule(_bridged).function)
4052
}
4153

54+
var vTables: VTableArray {
55+
VTableArray(bridged: PassContext_getVTables(_bridged))
56+
}
57+
4258
/// Run a closure with a `PassContext` for a function, which allows to modify that function.
4359
///
4460
/// Only a single `transform` can be alive at the same time, i.e. it's not allowed to nest

SwiftCompilerSources/Sources/SIL/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ add_swift_compiler_module(SIL
2525
SubstitutionMap.swift
2626
Type.swift
2727
Utils.swift
28-
Value.swift)
28+
Value.swift
29+
VTable.swift)
2930

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===--- VTable.swift -----------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SILBridging
14+
15+
public struct VTable : CustomStringConvertible, CustomReflectable {
16+
let bridged: BridgedVTable
17+
18+
public init(bridged: BridgedVTable) { self.bridged = bridged }
19+
20+
public struct Entry : CustomStringConvertible, CustomReflectable {
21+
fileprivate let bridged: BridgedVTableEntry
22+
23+
public var function: Function { SILVTableEntry_getFunction(bridged).function }
24+
25+
public var description: String {
26+
let stdString = SILVTableEntry_debugDescription(bridged)
27+
return String(_cxxString: stdString)
28+
}
29+
30+
public var customMirror: Mirror { Mirror(self, children: []) }
31+
}
32+
33+
public struct EntryArray : BridgedRandomAccessCollection {
34+
fileprivate let bridgedArray: BridgedArrayRef
35+
36+
public var startIndex: Int { return 0 }
37+
public var endIndex: Int { return Int(bridgedArray.numElements) }
38+
39+
public subscript(_ index: Int) -> Entry {
40+
precondition(index >= 0 && index < endIndex)
41+
return Entry(bridged: BridgedVTableEntry(ptr: bridgedArray.data! + index &* BridgedVTableEntrySize))
42+
}
43+
}
44+
45+
public var entries: EntryArray {
46+
EntryArray(bridgedArray: SILVTable_getEntries(bridged))
47+
}
48+
49+
public var description: String {
50+
let stdString = SILVTable_debugDescription(bridged)
51+
return String(_cxxString: stdString)
52+
}
53+
54+
public var customMirror: Mirror { Mirror(self, children: []) }
55+
}

include/swift/SIL/SILBridging.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
2323

2424
enum {
2525
BridgedOperandSize = 4 * sizeof(uintptr_t),
26-
BridgedSuccessorSize = 4 * sizeof(uintptr_t) + sizeof(uint64_t)
26+
BridgedSuccessorSize = 4 * sizeof(uintptr_t) + sizeof(uint64_t),
27+
BridgedVTableEntrySize = 5 * sizeof(uintptr_t)
2728
};
2829

2930
enum ChangeNotificationKind {
@@ -68,6 +69,14 @@ typedef struct {
6869
const void * _Nullable succ;
6970
} OptionalBridgedSuccessor;
7071

72+
typedef struct {
73+
const void * _Nonnull ptr;
74+
} BridgedVTable;
75+
76+
typedef struct {
77+
const void * _Nonnull ptr;
78+
} BridgedVTableEntry;
79+
7180
typedef struct {
7281
SwiftObject obj;
7382
} BridgedFunction;
@@ -233,6 +242,11 @@ llvm::StringRef SILGlobalVariable_getName(BridgedGlobalVar global);
233242
std::string SILGlobalVariable_debugDescription(BridgedGlobalVar global);
234243
SwiftInt SILGlobalVariable_isLet(BridgedGlobalVar global);
235244

245+
std::string SILVTable_debugDescription(BridgedVTable vTable);
246+
BridgedArrayRef SILVTable_getEntries(BridgedVTable vTable);
247+
std::string SILVTableEntry_debugDescription(BridgedVTableEntry entry);
248+
BridgedFunction SILVTableEntry_getFunction(BridgedVTableEntry entry);
249+
236250
OptionalBridgedBasicBlock SILBasicBlock_next(BridgedBasicBlock block);
237251
OptionalBridgedBasicBlock SILBasicBlock_previous(BridgedBasicBlock block);
238252
BridgedFunction SILBasicBlock_getFunction(BridgedBasicBlock block);

include/swift/SIL/SILBridgingUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/SIL/SILBridging.h"
1717
#include "swift/SIL/SILFunction.h"
1818
#include "swift/SIL/SILGlobalVariable.h"
19+
#include "swift/SIL/SILVTable.h"
1920
#include "llvm/ADT/StringRef.h"
2021

2122
#include <string>
@@ -84,6 +85,14 @@ inline SILGlobalVariable *castToGlobal(BridgedGlobalVar global) {
8485
return static_cast<SILGlobalVariable *>(global.obj);
8586
}
8687

88+
inline const SILVTable *castToVTable(BridgedVTable vTable) {
89+
return static_cast<const SILVTable *>(vTable.ptr);
90+
}
91+
92+
inline const SILVTableEntry *castToVTableEntry(BridgedVTableEntry entry) {
93+
return static_cast<const SILVTableEntry *>(entry.ptr);
94+
}
95+
8796
inline ValueOwnershipKind castToOwnership(BridgedOwnership ownership) {
8897
switch (ownership) {
8998
case Ownership_Unowned: return OwnershipKind::Unowned;

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ typedef struct {
2727
BridgedPassContext passContext;
2828
} BridgedInstructionPassCtxt;
2929

30+
typedef struct {
31+
const BridgedVTable * _Nullable vTables;
32+
size_t count;
33+
} BridgedVTableArray;
34+
3035
typedef struct {
3136
const void * _Nonnull aliasAnalysis;
3237
} BridgedAliasAnalysis;
@@ -166,6 +171,7 @@ OptionalBridgedFunction
166171
PassContext_firstFunctionInModule(BridgedPassContext context);
167172
OptionalBridgedFunction
168173
PassContext_nextFunctionInModule(BridgedFunction function);
174+
BridgedVTableArray PassContext_getVTables(BridgedPassContext context);
169175

170176
OptionalBridgedFunction
171177
PassContext_loadFunction(BridgedPassContext context, llvm::StringRef name);

lib/SIL/Utils/SILBridging.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,38 @@ SwiftInt SILGlobalVariable_isLet(BridgedGlobalVar global) {
549549
return castToGlobal(global)->isLet();
550550
}
551551

552+
//===----------------------------------------------------------------------===//
553+
// SILVTable
554+
//===----------------------------------------------------------------------===//
555+
556+
static_assert(BridgedVTableEntrySize == sizeof(SILVTableEntry),
557+
"wrong bridged VTableEntry size");
558+
559+
std::string SILVTable_debugDescription(BridgedVTable vTable) {
560+
std::string str;
561+
llvm::raw_string_ostream os(str);
562+
castToVTable(vTable)->print(os);
563+
str.pop_back(); // Remove trailing newline.
564+
return str;
565+
}
566+
567+
BridgedArrayRef SILVTable_getEntries(BridgedVTable vTable) {
568+
auto entries = castToVTable(vTable)->getEntries();
569+
return {(const unsigned char *)entries.data(), entries.size()};
570+
}
571+
572+
std::string SILVTableEntry_debugDescription(BridgedVTableEntry entry) {
573+
std::string str;
574+
llvm::raw_string_ostream os(str);
575+
castToVTableEntry(entry)->print(os);
576+
str.pop_back(); // Remove trailing newline.
577+
return str;
578+
}
579+
580+
BridgedFunction SILVTableEntry_getFunction(BridgedVTableEntry entry) {
581+
return {castToVTableEntry(entry)->getImplementation()};
582+
}
583+
552584
//===----------------------------------------------------------------------===//
553585
// SILInstruction
554586
//===----------------------------------------------------------------------===//

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,12 @@ PassContext_nextFunctionInModule(BridgedFunction function) {
15731573
return {&*nextIter};
15741574
}
15751575

1576+
BridgedVTableArray PassContext_getVTables(BridgedPassContext context) {
1577+
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();
1578+
auto vTables = mod->getVTables();
1579+
return {(const BridgedVTable *)vTables.data(), vTables.size()};
1580+
}
1581+
15761582
OptionalBridgedFunction
15771583
PassContext_loadFunction(BridgedPassContext context, StringRef name) {
15781584
SILModule *mod = castToPassInvocation(context)->getPassManager()->getModule();

0 commit comments

Comments
 (0)