@@ -169,7 +169,7 @@ fileprivate struct MetaProgramCounter {
169169/// ```
170170/// | Offset | Description |
171171/// |------------------------------------|----------------------|
172- /// | 0 ~ max(params, results)-1 | Frame header |
172+ /// | SP-3 ~ SP-( max(params, results)+3) | Frame header |
173173/// | SP-3 | * Saved Instance |
174174/// | SP-2 | * Saved PC |
175175/// | SP-1 | * Saved SP |
@@ -190,19 +190,19 @@ fileprivate struct MetaProgramCounter {
190190
191191struct FrameHeaderLayout {
192192 let type : FunctionType
193- let paramResultBase : VReg
193+ let size : VReg
194194
195195 init ( type: FunctionType ) {
196196 self . type = type
197- self . paramResultBase = Self . size ( of: type)
197+ self . size = Self . size ( of: type)
198198 }
199199
200200 func paramReg( _ index: Int ) -> VReg {
201- VReg ( index) - paramResultBase
201+ VReg ( index) - size
202202 }
203203
204204 func returnReg( _ index: Int ) -> VReg {
205- return VReg ( index) - paramResultBase
205+ return VReg ( index) - size
206206 }
207207
208208 internal static func size( of: FunctionType ) -> VReg {
@@ -236,13 +236,17 @@ struct StackLayout {
236236 }
237237
238238 func localReg( _ index: LocalIndex ) -> VReg {
239- if index < frameHeader . type . parameters . count {
239+ if isParameter ( index) {
240240 return frameHeader. paramReg ( Int ( index) )
241241 } else {
242242 return VReg ( index) - VReg( frameHeader. type. parameters. count)
243243 }
244244 }
245245
246+ func isParameter( _ index: LocalIndex ) -> Bool {
247+ index < frameHeader. type. parameters. count
248+ }
249+
246250 func constReg( _ index: Int ) -> VReg {
247251 return VReg ( numberOfLocals + index)
248252 }
@@ -990,11 +994,21 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
990994 }
991995
992996 private mutating func visitReturnLike( ) throws {
993- preserveOnStack ( depth : self . type . results . count )
997+ var copies : [ ( source : VReg , dest : VReg ) ] = [ ]
994998 for (index, resultType) in self . type. results. enumerated ( ) . reversed ( ) {
995999 guard let operand = try popOperand ( resultType) else { continue }
996- let source = ensureOnVReg ( operand)
1000+ var source = ensureOnVReg ( operand)
1001+ if case . local( let localIndex) = operand, stackLayout. isParameter ( localIndex) {
1002+ // Parameter space is shared with return values, so we need to copy it to the stack
1003+ // before copying to the return slot to avoid overwriting the parameter value.
1004+ let copyTo = valueStack. stackRegBase + VReg( valueStack. height)
1005+ emitCopyStack ( from: localReg ( localIndex) , to: copyTo)
1006+ source = copyTo
1007+ }
9971008 let dest = returnReg ( index)
1009+ copies. append ( ( source, dest) )
1010+ }
1011+ for (source, dest) in copies {
9981012 emitCopyStack ( from: source, to: dest)
9991013 }
10001014 }
0 commit comments