📄 codeblock.vb
字号:
Else Emitter.EmitLeave(Info, Me.EndMethodLabel) End If Me.UnstructuredExceptionLabels.Add(UnstructuredSwitchHandlerEnd) Dim tmpVar As LocalBuilder = Info.ILGen.DeclareLocal(Compiler.TypeCache.System_Int32) If Me.HasResume Then 'Increment the instruction pointer index with one, then jump to the switch Info.ILGen.MarkLabel(ResumeNextExceptionHandler) Emitter.EmitLoadI4Value(Info, -1) Emitter.EmitStoreVariable(Info, IsInUnstructuredHandler) Emitter.EmitLoadVariable(Info, CurrentInstruction) Emitter.EmitLoadI4Value(Info, 1) Emitter.EmitAdd(Info, Compiler.TypeCache.System_Int32) Emitter.EmitStoreVariable(Info, tmpVar) Emitter.EmitLeave(Info, UnstructuredSwitchHandler) End If 'Emit the actual handler Info.ILGen.MarkLabel(UnstructuredExceptionHandler) Emitter.EmitLoadI4Value(Info, -1) Emitter.EmitStoreVariable(Info, IsInUnstructuredHandler) Emitter.EmitLoadVariable(Info, UnstructuredExceptionHandlerVariable) Emitter.EmitStoreVariable(Info, tmpVar) Info.ILGen.MarkLabel(UnstructuredSwitchHandler) Emitter.EmitLoadVariable(Info, tmpVar) Emitter.EmitSwitch(Info, UnstructuredExceptionLabels.ToArray) Info.ILGen.MarkLabel(UnstructuredSwitchHandlerEnd) Emitter.EmitLeave(Info, EndMethodLabel) 'Catch the exception 'create a filter, only handle the exception if it is of type Exception, 'if it was not raised when in the unstructured handler and if there actually 'is a registered exception handler. Info.ILGen.BeginExceptFilterBlock() Info.Stack.Push(Compiler.TypeCache.System_Object) Emitter.EmitIsInst(Info, Compiler.TypeCache.System_Object, Compiler.TypeCache.System_Exception) Emitter.EmitLoadNull(Info.Clone(True, False, Compiler.TypeCache.System_Exception)) Emitter.EmitGT_Un(Info, Compiler.TypeCache.System_Exception) 'TypeOf ... Is System.Exception Emitter.EmitLoadVariable(Info, Me.UnstructuredExceptionHandlerVariable) Emitter.EmitLoadI4Value(Info, 0) Emitter.EmitGT(Info, Compiler.TypeCache.System_Int32) 'if a handler is registered. Emitter.EmitAnd(Info, Compiler.TypeCache.System_Boolean) Emitter.EmitLoadVariable(Info, Me.IsInUnstructuredHandler) Emitter.EmitLoadI4Value(Info, 0) Emitter.EmitGT(Info, Compiler.TypeCache.System_Int32) 'if code is in a unstructured handler or not Emitter.EmitAnd(Info, Compiler.TypeCache.System_Boolean) Info.Stack.Pop(Compiler.TypeCache.System_Boolean) 'create the catch block Info.ILGen.BeginCatchBlock(Nothing) Info.Stack.Push(Compiler.TypeCache.System_Object) Emitter.EmitCastClass(Info, Compiler.TypeCache.System_Object, Compiler.TypeCache.System_Exception) Emitter.EmitCall(Info, Compiler.TypeCache.MS_VB_CS_ProjectData__SetProjectError_Exception) Emitter.EmitLeave(Info, UnstructuredExceptionHandler) Info.ILGen.EndExceptionBlock() 'Create an internal exception if the code gets here. Info.ILGen.MarkLabel(m_InternalExceptionLocation) Emitter.EmitLoadI4Value(Info, -2146828237) Emitter.EmitCall(Info, Compiler.TypeCache.MS_VB_CS_ProjectData__CreateProjectError_Int32) Emitter.EmitThrow(Info) Info.ILGen.MarkLabel(EndMethodLabel) Dim veryMethodEnd As Label = Info.ILGen.DefineLabel Emitter.EmitLoadVariable(Info.Clone(True, False, Compiler.TypeCache.System_Boolean), IsInUnstructuredHandler) Info.Stack.SwitchHead(Compiler.TypeCache.System_Int32, Compiler.TypeCache.System_Boolean) Emitter.EmitBranchIfFalse(Info, veryMethodEnd) Emitter.EmitCall(Info, Compiler.TypeCache.MS_VB_CS_ProjectData__ClearProjectError) Info.ILGen.MarkLabel(veryMethodEnd) If retvar IsNot Nothing Then Emitter.MarkLabel(Info, m_EndOfMethodLabel.Value) Emitter.EmitLoadVariable(Info, retvar) Info.ILGen.Emit(OpCodes.Ret) Else Emitter.MarkLabel(Info, m_EndOfMethodLabel.Value) Info.ILGen.Emit(OpCodes.Ret) End If Return result End Function ReadOnly Property UpmostBlock() As CodeBlock Get Dim result As CodeBlock = Nothing Dim tmp As CodeBlock tmp = Me Do Until tmp Is Nothing result = tmp tmp = tmp.FindFirstParent(Of CodeBlock)() Loop Return result End Get End Property ''' <summary> ''' Call this function from a method beeing emitted. ''' </summary> ''' <param name="Method"></param> ''' <returns></returns> ''' <remarks></remarks> Friend Overloads Function GenerateCode(ByVal Method As IMethod) As Boolean Dim result As Boolean = True#If EXTENDEDDEBUG Then Compiler.Report.WriteLine(vbnc.Report.ReportLevels.Debug, "Emitting method: " & Method.FullName)#End If Dim info As New EmitInfo(Method) m_EndOfMethodLabel = Emitter.DefineLabel(info) If Me.HasUnstructuredExceptionHandling Then result = GenerateUnstructuredStart(info) AndAlso result End If#If DEBUG Then If Method.MemberDescriptor.MemberType = MemberTypes.Constructor = False Then info.ILGen.Emit(OpCodes.Nop) End If#End If result = GenerateCode(info) AndAlso result If Me.HasUnstructuredExceptionHandling = False Then Emitter.MarkLabel(info, m_EndOfMethodLabel.Value) End If Dim retvar As LocalBuilder = Method.DefaultReturnVariable If retvar IsNot Nothing Then Emitter.EmitLoadVariable(info, retvar) Else Helper.Assert(Method.HasReturnValue = False) End If If Me.HasUnstructuredExceptionHandling Then result = GenerateUnstructuredEnd(Method, info) AndAlso result Else Emitter.EmitRet(info)#If DEBUGREFLECTION Then Dim obj As Object If TypeOf info.Method Is ConstructorDeclaration Then obj = CType(info.Method, ConstructorDeclaration).ConstructorBuilder Else obj = info.Method.MethodBuilder End If Helper.DebugReflection_AppendLine("{0} = {1}.GetILGenerator", info.ILGen, obj) Helper.DebugReflection_AppendLine("{0}.Emit (System.Reflection.Emit.Opcodes.Ret)", info.ILGen)#End If End If#If EXTENDEDDEBUG Then Compiler.Report.WriteLine(vbnc.Report.ReportLevels.Debug, "Method " & Method.FullName & " emitted (ID: " & Method.ObjectID.ToString & ")")#End If#If EXTENDEDDEBUG Then If info.Stack.Count <> 0 Then Throw New InternalException("End of method " & Method.FullName & " reached, but stack is not empty.") End If#End If Return result End Function Private Function CreateLabelForCurrentInstruction(ByVal Info As EmitInfo) As Boolean Dim result As Boolean = True If UpmostBlock.HasResume Then Dim index As Integer Dim lbl As Label = Info.ILGen.DefineLabel UpmostBlock.UnstructuredExceptionLabels.Add(lbl) index = UpmostBlock.UnstructuredExceptionLabels.IndexOf(lbl) Info.ILGen.MarkLabel(lbl) Emitter.EmitLoadI4Value(Info, index) Emitter.EmitStoreVariable(Info, UpmostBlock.CurrentInstruction) End If Return result End Function Friend Overrides Function GenerateCode(ByVal Info As EmitInfo) As Boolean Dim result As Boolean = True#If DEBUG Then Info.Stack.CheckStackEmpty("Start of block " & Me.GetType.Name & " - " & Location.ToString(Compiler) & ") in " & Info.Method.FullName & " reached, but stack is not empty.")#End If For i As Integer = 0 To m_Variables.Count - 1 Dim var As VariableDeclaration = m_Variables(i) result = CreateLabelForCurrentInstruction(Info) AndAlso result result = var.DefineLocalVariable(Info) AndAlso result Next For i As Integer = 0 To m_Sequence.Count - 1 Dim stmt As BaseObject = m_Sequence.Item(i)#If DEBUG Then Info.Stack.CheckStackEmpty("Start of statement #" & (i + 1).ToString & " (" & stmt.GetType.Name & " - " & stmt.Location.ToString(Compiler) & ") in " & Info.Method.FullName & " reached, but stack is not empty.")#End If Emitter.MarkSequencePoint(Info, stmt.Location) result = CreateLabelForCurrentInstruction(Info) AndAlso result result = stmt.GenerateCode(Info) AndAlso result#If DEBUG Then Info.Stack.CheckStackEmpty("End of statement #" & (i + 1).ToString & " (" & stmt.GetType.Name & " - " & stmt.Location.ToString(Compiler) & ") in " & Info.Method.FullName & " reached, but stack is not empty.")#End If Next Return result End Function ReadOnly Property Variables() As Nameables(Of VariableDeclaration) Get Return m_Variables End Get End Property Overridable ReadOnly Property IsOneLiner() As Boolean Get If TypeOf Me.Parent Is CodeBlock Then Return DirectCast(Me.Parent, CodeBlock).IsOneLiner ElseIf TypeOf Me.Parent Is Statement Then Return DirectCast(Me.Parent, Statement).IsOneLiner Else Return False End If End Get End Property Public Overrides Function ResolveTypeReferences() As Boolean Dim result As Boolean = True For i As Integer = 0 To m_Variables.Count - 1 result = m_Variables(i).ResolveTypeReferences AndAlso result 'vbnc.Helper.Assert(result = (Report.Errors = 0)) Next For Each obj As Statement In m_Statements result = obj.ResolveTypeReferences AndAlso result 'vbnc.Helper.Assert(result = (Report.Errors = 0)) Next Return result End Function Public Overrides Function ResolveCode(ByVal Info As ResolveInfo) As Boolean Dim result As Boolean = True For i As Integer = 0 To m_Variables.Count - 1 result = m_Variables(i).ResolveMember(Info) AndAlso result result = m_Variables(i).ResolveCode(Info) AndAlso result 'Helper.Assert(result = (Compiler.Report.Errors = 0)) Next For Each obj As Statement In m_Statements result = obj.ResolveStatement(Info) AndAlso result 'Helper.Assert(result = (Compiler.Report.Errors = 0)) Next Return result End Function Function FindVariable(ByVal Name As String) As IAttributableNamedDeclaration Dim found As Generic.List(Of INameable) found = m_Variables.Index.Item(Name) If found Is Nothing Then Return Nothing ElseIf found.Count = 1 Then Return DirectCast(found(0), IAttributableNamedDeclaration) ElseIf found.Count > 1 Then Throw New InternalException(Me) Else Return Nothing End If End FunctionEnd Class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -