Swift SIL: add some APIs

* `Options.assertConfiguration`
* `Argument.isIndirectResult`
* in `Function`: `selfArgument`, `isTransparent`, `performanceConstraints` and `inlineStrategy`
* `BuiltinInst.substitutionMap`
* `SubstitutionMap.replacementTypes`
* `Type.canBeClass`
This commit is contained in:
Erik Eckstein
2023-05-09 20:27:19 +02:00
parent 82734b6ac2
commit b9169064c6
9 changed files with 143 additions and 0 deletions

View File

@@ -27,4 +27,18 @@ struct Options {
func enableSimplification(for inst: Instruction) -> Bool {
_bridged.enableSimplificationFor(inst.bridged)
}
enum AssertConfiguration {
case enabled
case disabled
case unknown
}
var assertConfiguration: AssertConfiguration {
switch _bridged.getAssertConfiguration() {
case .Debug: return .enabled
case .Release, .Unchecked: return .disabled
default: return .unknown
}
}
}

View File

@@ -42,6 +42,10 @@ final public class FunctionArgument : Argument {
public var convention: ArgumentConvention {
bridged.getConvention().convention
}
public var isIndirectResult: Bool {
return index < parentFunction.numIndirectResultArguments
}
}
final public class BlockArgument : Argument {

View File

@@ -79,6 +79,8 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
return selfIdx
}
public var selfArgument: FunctionArgument { arguments[selfArgumentIndex] }
public var argumentTypes: ArgumentTypeArray { ArgumentTypeArray(function: self) }
public var resultType: Type { bridged.getSILResultType().type }
@@ -122,6 +124,8 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
/// This means that the function terminates the program.
public var isProgramTerminationPoint: Bool { hasSemanticsAttribute("programtermination_point") }
public var isTransparent: Bool { bridged.isTransparent() }
/// True if this is a `[global_init]` function.
///
/// Such a function is typically a global addressor which calls the global's
@@ -187,6 +191,37 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
}
}
public enum PerformanceConstraints {
case none
case noAllocations
case noLocks
}
public var performanceConstraints: PerformanceConstraints {
switch bridged.getPerformanceConstraints() {
case .None: return .none
case .NoAllocation: return .noAllocations
case .NoLocks: return .noLocks
default: fatalError("unknown performance constraint")
}
}
public enum InlineStrategy {
case automatic
case never
case always
}
public var inlineStrategy: InlineStrategy {
switch bridged.getInlineStrategy() {
case .InlineDefault: return .automatic
case .NoInline: return .never
case .AlwaysInline: return .always
default:
fatalError()
}
}
/// True, if the function runs with a swift 5.1 runtime.
/// Note that this is function specific, because inlinable functions are de-serialized
/// in a client module, which might be compiled with a different deployment target.

View File

@@ -365,6 +365,10 @@ final public class BuiltinInst : SingleValueInstruction {
public var id: ID {
return bridged.BuiltinInst_getID()
}
public var substitutionMap: SubstitutionMap {
SubstitutionMap(bridged.BuiltinInst_getSubstitutionMap())
}
}
final public class UpcastInst : SingleValueInstruction, UnaryInstruction {

View File

@@ -24,4 +24,9 @@ public struct SubstitutionMap {
}
public var isEmpty: Bool { bridged.empty() }
public var replacementTypes: OptionalTypeArray {
let types = BridgedTypeArray.fromReplacementTypes(bridged)
return OptionalTypeArray(bridged: types)
}
}

View File

@@ -43,6 +43,8 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
public var isMetatype: Bool { bridged.isMetatype() }
public var isNoEscapeFunction: Bool { bridged.isNoEscapeFunction() }
public var canBeClass: swift.TypeTraitResult { bridged.canBeClass() }
/// Can only be used if the type is in fact a nominal type (`isNominal` is true).
public var nominal: NominalTypeDecl {
NominalTypeDecl(bridged: BridgedNominalTypeDecl(decl: bridged.getNominalOrBoundGenericNominal()))
@@ -82,6 +84,26 @@ extension Type: Equatable {
}
}
public struct OptionalTypeArray : RandomAccessCollection, CustomReflectable {
private let bridged: BridgedTypeArray
public var startIndex: Int { return 0 }
public var endIndex: Int { return bridged.getCount() }
public init(bridged: BridgedTypeArray) {
self.bridged = bridged
}
public subscript(_ index: Int) -> Type? {
bridged.getAt(index).typeOrNil
}
public var customMirror: Mirror {
let c: [Mirror.Child] = map { (label: nil, value: $0 ?? "<invalid>") }
return Mirror(self, children: c)
}
}
public struct NominalFieldsArray : RandomAccessCollection, FormattedLikeArray {
fileprivate let type: Type
fileprivate let function: Function
@@ -118,6 +140,7 @@ public struct TupleElementArray : RandomAccessCollection, FormattedLikeArray {
extension swift.SILType {
var type: Type { Type(bridged: self) }
var typeOrNil: Type? { isNull() ? nil : type }
}
// TODO: use an AST type for this once we have it

View File

@@ -237,6 +237,10 @@ struct BridgedFunction {
return getFunction()->isAvailableExternally();
}
bool isTransparent() const {
return getFunction()->isTransparent() == swift::IsTransparent;
}
bool isGlobalInitFunction() const {
return getFunction()->isGlobalInit();
}
@@ -253,6 +257,20 @@ struct BridgedFunction {
return getFunction()->getEffectsKind();
}
swift::PerformanceConstraints getPerformanceConstraints() const {
return getFunction()->getPerfConstraints();
}
enum class InlineStrategy {
InlineDefault = swift::InlineDefault,
NoInline = swift::NoInline,
AlwaysInline = swift::AlwaysInline
};
InlineStrategy getInlineStrategy() const {
return (InlineStrategy)getFunction()->getInlineStrategy();
}
bool needsStackProtection() const {
return getFunction()->needsStackProtection();
}
@@ -364,6 +382,25 @@ struct OptionalBridgedInstruction {
}
};
struct BridgedTypeArray {
llvm::ArrayRef<swift::Type> typeArray;
SWIFT_IMPORT_UNSAFE
static BridgedTypeArray fromReplacementTypes(swift::SubstitutionMap substMap) {
return {substMap.getReplacementTypes()};
}
SwiftInt getCount() const { return SwiftInt(typeArray.size()); }
SWIFT_IMPORT_UNSAFE
swift::SILType getAt(SwiftInt index) const {
auto ty = swift::CanType(typeArray[index]);
if (ty->isLegalSILType())
return swift::SILType::getPrimitiveObjectType(ty);
return swift::SILType();
}
};
struct BridgedInstruction {
SwiftObject obj;
@@ -457,6 +494,12 @@ struct BridgedInstruction {
return getAs<swift::BuiltinInst>()->getBuiltinInfo().ID;
}
SWIFT_IMPORT_UNSAFE
swift::SubstitutionMap BuiltinInst_getSubstitutionMap() const {
return getAs<swift::BuiltinInst>()->getSubstitutions();
}
bool AddressToPointerInst_needsStackProtection() const {
return getAs<swift::AddressToPointerInst>()->needsStackProtection();
}

View File

@@ -414,6 +414,10 @@ public:
return getASTType()->hasOpenedExistential();
}
TypeTraitResult canBeClass() const {
return getASTType()->canBeClass();
}
/// Returns true if the referenced type is expressed in terms of one
/// or more local archetypes.
bool hasLocalArchetype() const {

View File

@@ -431,6 +431,17 @@ struct BridgedPassContext {
return mod->getOptions().EnableMoveInoutStackProtection;
}
enum class AssertConfiguration {
Debug = swift::SILOptions::Debug,
Release = swift::SILOptions::Release,
Unchecked = swift::SILOptions::Unchecked
};
AssertConfiguration getAssertConfiguration() const {
swift::SILModule *mod = invocation->getPassManager()->getModule();
return (AssertConfiguration)mod->getOptions().AssertConfig;
}
bool enableSimplificationFor(BridgedInstruction inst) const;
};