From 2e5e9d28b7fa7f12980925fee65d831428fa5073 Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 14:39:38 +0200 Subject: [PATCH 1/6] Request sink access on move sources during access reification --- Sources/IR/Analysis/Module+AccessReification.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/IR/Analysis/Module+AccessReification.swift b/Sources/IR/Analysis/Module+AccessReification.swift index 665468380..3a7caa68d 100644 --- a/Sources/IR/Analysis/Module+AccessReification.swift +++ b/Sources/IR/Analysis/Module+AccessReification.swift @@ -83,7 +83,7 @@ extension Module { case is Load: return [.sink] case is Move: - return [.inout] + return u.index == 0 ? [.sink] : [.inout] case is ProjectBundle: return requests(projectBundle: u) default: From c6b7d283aa7caa7511c1a0ef76a3dd8a0856a78b Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 16:35:37 +0200 Subject: [PATCH 2/6] Mangle method bundle declarations --- Sources/IR/Mangling/Demangler.swift | 6 ++++ Sources/IR/Mangling/Mangler.swift | 35 ++++++++++++++++++++++ Sources/IR/Mangling/ManglingOperator.swift | 6 ++++ 3 files changed, 47 insertions(+) diff --git a/Sources/IR/Mangling/Demangler.swift b/Sources/IR/Mangling/Demangler.swift index 142967e2c..a563d6654 100644 --- a/Sources/IR/Mangling/Demangler.swift +++ b/Sources/IR/Mangling/Demangler.swift @@ -113,6 +113,12 @@ struct Demangler { return nil case .monomorphizedFunctionDecl: return nil + case .methodDecl: + return nil + case .methodImpl: + return nil + case .methodType: + return nil case .synthesizedFunctionDecl: return nil case .conformanceConstraint, .equalityConstraint, .valueConstraint, .whereClause: diff --git a/Sources/IR/Mangling/Mangler.swift b/Sources/IR/Mangling/Mangler.swift index 874cb0964..43d7917c8 100644 --- a/Sources/IR/Mangling/Mangler.swift +++ b/Sources/IR/Mangling/Mangler.swift @@ -145,6 +145,10 @@ struct Mangler { write(initializer: InitializerDecl.ID(symbol)!, to: &output) case MatchCase.self: write(anonymousScope: symbol, to: &output) + case MethodDecl.self: + write(methodDecl: MethodDecl.ID(symbol)!, to: &output) + case MethodImpl.self: + write(methodImpl: MethodImpl.ID(symbol)!, to: &output) case ModuleDecl.self: write(entity: ModuleDecl.ID(symbol)!, to: &output) case NamespaceDecl.self: @@ -238,6 +242,19 @@ struct Mangler { mangle(type: program[d].type, to: &output) } + /// Writes the mangled representation of `d` to `output`. + private mutating func write(methodDecl d: MethodDecl.ID, to output: inout Output) { + write(operator: .methodDecl, to: &output) + write(string: program.ast[d].identifier.value, to: &output) + mangle(type: program[d].type, to: &output) + } + + /// Writes the mangled representation of `d` to `output`. + private mutating func write(methodImpl d: MethodImpl.ID, to output: inout Output) { + write(operator: .methodImpl, to: &output) + write(base64Digit: program.ast[d].introducer.value, to: &output) + } + /// Writes the mangled representation of `d` to `output`. private mutating func write(subscriptDecl d: SubscriptDecl.ID, to output: inout Output) { if program.ast[d].isProperty { @@ -383,6 +400,9 @@ struct Mangler { case let t as LambdaType: write(lambda: t, to: &output) + case let t as MethodType: + write(method: t, to: &output) + case let t as MetatypeType: write(operator: .metatypeType, to: &output) mangle(type: t.instance, to: &output) @@ -499,6 +519,21 @@ struct Mangler { mangle(type: t.output, to: &output) } + /// Writes the mangled representation of `symbol` to `output`. + private mutating func write(method t: MethodType, to output: inout Output) { + write(operator: .methodType, to: &output) + write(base64Digit: t.capabilities, to: &output) + mangle(type: t.receiver, to: &output) + + write(integer: t.inputs.count, to: &output) + for i in t.inputs { + write(string: i.label ?? "", to: &output) + mangle(type: i.type, to: &output) + } + + mangle(type: t.output, to: &output) + } + /// Writes the mangled representation of `symbol` to `output`. private mutating func write(subscriptType t: SubscriptType, to output: inout Output) { write(operator: .subscriptType, to: &output) diff --git a/Sources/IR/Mangling/ManglingOperator.swift b/Sources/IR/Mangling/ManglingOperator.swift index cd6bb5206..835805489 100644 --- a/Sources/IR/Mangling/ManglingOperator.swift +++ b/Sources/IR/Mangling/ManglingOperator.swift @@ -22,6 +22,10 @@ public enum ManglingOperator: String { case existentializedFunctionDecl = "eF" + case methodDecl = "hF" + + case methodImpl = "iF" + case monomorphizedFunctionDecl = "mF" case staticFunctionDecl = "sF" @@ -76,6 +80,8 @@ public enum ManglingOperator: String { case genericTypeParameterType = "gT" + case methodType = "hT" + case lambdaType = "lT" case metatypeType = "mT" From 6b1f457b57c7c6407054695d016cc04617fa11a7 Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 16:37:05 +0200 Subject: [PATCH 3/6] Stand up the call bundle reification pass --- .../Module+CallBundleReification.swift | 32 +++++++++++++++++++ Sources/IR/Module.swift | 1 + 2 files changed, 33 insertions(+) create mode 100644 Sources/IR/Analysis/Module+CallBundleReification.swift diff --git a/Sources/IR/Analysis/Module+CallBundleReification.swift b/Sources/IR/Analysis/Module+CallBundleReification.swift new file mode 100644 index 000000000..3dc82a4d1 --- /dev/null +++ b/Sources/IR/Analysis/Module+CallBundleReification.swift @@ -0,0 +1,32 @@ +import Core + +extension Module { + + /// Replace occurrences of `call_bundle` by `call` depending on the uses of their first operands, + /// reporting errors and warnings to `diagnostics`. + /// + /// - Requires: `f` is in `self`. + public mutating func reifyCallsToBundles(in f: Function.ID, diagnostics: inout DiagnosticSet) { + for i in blocks(in: f).map(instructions(in:)).joined() where self[i] is CallBundle { + reify(callBundle: i, for: .let) + } + } + + private mutating func reify(callBundle i: InstructionID, for k: AccessEffect) { + let s = self[i] as! CallBundle + assert(s.capabilities.contains(k)) + + var arguments = Array(s.arguments) + let r = makeAccess(k, from: arguments[0], at: s.site) + arguments[0] = .register(insert(r, before: i)) + + let b = Block.ID(containing: i) + let f = FunctionReference( + to: s.variants[k]!, in: self, specializedBy: s.bundle.arguments, in: self[b].scope) + + let reified = makeCall( + applying: .constant(f), to: arguments, writingResultTo: s.output, at: s.site) + replace(i, with: reified) + } + +} diff --git a/Sources/IR/Module.swift b/Sources/IR/Module.swift index 2865a9953..162c0a621 100644 --- a/Sources/IR/Module.swift +++ b/Sources/IR/Module.swift @@ -202,6 +202,7 @@ public struct Module { } try run({ removeDeadCode(in: $0, diagnostics: &log) }) + try run({ reifyCallsToBundles(in: $0, diagnostics: &log) }) try run({ reifyAccesses(in: $0, diagnostics: &log) }) try run({ closeBorrows(in: $0, diagnostics: &log) }) try run({ normalizeObjectStates(in: $0, diagnostics: &log) }) From 4a97a41032c99abc2dd24c815486adcf14810ce0 Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 16:48:30 +0200 Subject: [PATCH 4/6] Generate IR lowering method declarations --- Sources/IR/Emitter.swift | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Sources/IR/Emitter.swift b/Sources/IR/Emitter.swift index 6bfca5f9a..8e943007d 100644 --- a/Sources/IR/Emitter.swift +++ b/Sources/IR/Emitter.swift @@ -319,6 +319,46 @@ struct Emitter { insert(module.makeReturn(at: returnSite)) } + /// Inserts the IR for `d`. + private mutating func lower(method d: MethodDecl.ID) { + for i in ast[d].impls { + lower(methodImpl: i) + } + } + + /// Inserts the IR for `d`. + private mutating func lower(methodImpl d: MethodImpl.ID) { + let f = module.demandDeclaration(lowering: d) + guard let b = ast[d].body else { return } + + // Create the function entry. + let entry = module.appendEntry(in: program.scopeContainingBody(of: d)!, to: f) + + // Configure the locals. + var locals = DeclProperty() + locals[ast[d].receiver] = .parameter(entry, 0) + + let bundle = MethodDecl.ID(program[d].scope)! + for (i, p) in ast[bundle].parameters.enumerated() { + locals[p] = .parameter(entry, i + 1) + } + + let bodyFrame = Frame(locals: locals) + + // Emit the body. + self.insertionPoint = .end(of: entry) + switch b { + case .block(let s): + let returnType = LambdaType(program[d].type)!.output + let returnSite = pushing(bodyFrame, { $0.lowerStatements(s, expecting: returnType) }) + insert(module.makeReturn(at: returnSite)) + + case .expr(let e): + pushing(bodyFrame, { $0.emitStore(value: e, to: $0.returnValue!) }) + insert(module.makeReturn(at: ast[e].site)) + } + } + /// Inserts the IR for `d`. private mutating func lower(subscript d: SubscriptDecl.ID) { for i in ast[d].impls { @@ -418,6 +458,8 @@ struct Emitter { lower(function: .init(m)!) case InitializerDecl.self: lower(initializer: .init(m)!) + case MethodDecl.self: + lower(method: .init(m)!) case SubscriptDecl.self: lower(subscript: .init(m)!) default: From 9f4ab57dfdd4d255887cbe02e4377ab22d194206 Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 16:50:41 +0200 Subject: [PATCH 5/6] Test call to method bundle --- .../EndToEndTests/TestCases/MethodBundle.hylo | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Tests/EndToEndTests/TestCases/MethodBundle.hylo diff --git a/Tests/EndToEndTests/TestCases/MethodBundle.hylo b/Tests/EndToEndTests/TestCases/MethodBundle.hylo new file mode 100644 index 000000000..96959d646 --- /dev/null +++ b/Tests/EndToEndTests/TestCases/MethodBundle.hylo @@ -0,0 +1,20 @@ +//- compileAndRun expecting: success + +type A: Deinitializable { + + public var x: Int + + public memberwise init + + public fun foo() -> Int { + let { x.copy() } + sink { x } + } + +} + +public fun main() { + var a = A(x: 42) + precondition(a.foo() == 42) + precondition(a.foo() == 42) +} From eb641e88f26c09b1584e478a00e404993af40b12 Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 16:56:28 +0200 Subject: [PATCH 6/6] Apply swift-format --- Sources/FrontEnd/TypeChecking/TypeChecker.swift | 2 +- Sources/IR/Emitter.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/FrontEnd/TypeChecking/TypeChecker.swift b/Sources/FrontEnd/TypeChecking/TypeChecker.swift index d11758bf7..a3e0e43d9 100644 --- a/Sources/FrontEnd/TypeChecking/TypeChecker.swift +++ b/Sources/FrontEnd/TypeChecking/TypeChecker.swift @@ -152,7 +152,7 @@ struct TypeChecker { return [ program.ast.movableTrait, program.ast.deinitializableTrait, - program.ast.foreignConvertibleTrait + program.ast.foreignConvertibleTrait, ] } diff --git a/Sources/IR/Emitter.swift b/Sources/IR/Emitter.swift index 8e943007d..371169655 100644 --- a/Sources/IR/Emitter.swift +++ b/Sources/IR/Emitter.swift @@ -1468,8 +1468,9 @@ struct Emitter { writingResultTo storage: Operand, at site: SourceRange ) { let o = insert(module.makeAccess(.set, from: storage, at: site))! - insert(module.makeCallBundle( - applying: .init(callee, in: insertionScope!), to: arguments, writingResultTo: o, at: site)) + insert( + module.makeCallBundle( + applying: .init(callee, in: insertionScope!), to: arguments, writingResultTo: o, at: site)) insert(module.makeEndAccess(o, at: site)) }