@@ -298,7 +298,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
298298 enum Kind {
299299 case block( root: Bool )
300300 case loop
301- case `if`( elseLabel: LabelRef , endLabel: LabelRef )
301+ case `if`( elseLabel: LabelRef , endLabel: LabelRef , isElse : Bool )
302302
303303 static var block : Kind { . block( root: false ) }
304304 }
@@ -1113,7 +1113,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11131113 controlStack. pushFrame (
11141114 ControlStack . ControlFrame (
11151115 blockType: blockType, stackHeight: stackHeight, continuation: endLabel,
1116- kind: . if( elseLabel: elseLabel, endLabel: endLabel)
1116+ kind: . if( elseLabel: elseLabel, endLabel: endLabel, isElse : false )
11171117 )
11181118 )
11191119 guard let condition = condition else { return }
@@ -1130,8 +1130,8 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11301130 }
11311131
11321132 mutating func visitElse( ) throws -> Output {
1133- let frame = try controlStack. currentFrame ( )
1134- guard case let . if( elseLabel, endLabel) = frame. kind else {
1133+ var frame = try controlStack. currentFrame ( )
1134+ guard case let . if( elseLabel, endLabel, _ ) = frame. kind else {
11351135 throw TranslationError ( " Expected `if` control frame on top of the stack for `else` but got \( frame) " )
11361136 }
11371137 preserveOnStack ( depth: valueStack. height - frame. stackHeight)
@@ -1141,7 +1141,18 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11411141 let offset = endPC. offsetFromHead - selfPC. offsetFromHead
11421142 return Int32 ( offset)
11431143 }
1144- try valueStack. truncate ( height: frame. stackHeight)
1144+ for result in frame. blockType. results. reversed ( ) {
1145+ guard try checkBeforePop ( typeHint: result, controlFrame: frame) else { continue }
1146+ _ = try valueStack. pop ( result)
1147+ }
1148+ guard valueStack. height == frame. stackHeight else {
1149+ throw ValidationError ( " values remaining on stack at end of block " )
1150+ }
1151+ _ = controlStack. popFrame ( )
1152+ frame. kind = . if( elseLabel: elseLabel, endLabel: endLabel, isElse: true )
1153+ frame. reachable = true
1154+ controlStack. pushFrame ( frame)
1155+
11451156 // Re-push parameters
11461157 for parameter in frame. blockType. parameters {
11471158 _ = valueStack. push ( parameter)
@@ -1179,6 +1190,14 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11791190 return
11801191 }
11811192
1193+ if case . if( _, _, isElse: false ) = poppedFrame. kind {
1194+ // `if` inst without `else` must have the same parameter and result types
1195+ let blockType = poppedFrame. blockType
1196+ guard blockType. parameters == blockType. results else {
1197+ throw TranslationError ( " Expected the same parameter and result types for `if` block but got \( blockType) " )
1198+ }
1199+ }
1200+
11821201 // NOTE: `valueStack.height - poppedFrame.stackHeight` is usually the same as `poppedFrame.copyCount`
11831202 // but it's not always the case when this block is already unreachable.
11841203 preserveOnStack ( depth: Int ( valueStack. height - poppedFrame. stackHeight) )
0 commit comments