⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emitcodegen.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
        else 
            m_ilGenerator.Emit(code, iSlot);
        
    }
    
    void Emit_Ldloc(System.Reflection.Emit.LocalBuilder l)
    {        
       m_ilGenerator.Emit(OpCodes.Ldloc_S, l);        
    }
    
    void Emit_LdlocA(System.Reflection.Emit.LocalBuilder l)
    {        
        m_ilGenerator.Emit(OpCodes.Ldloca_S, l);        
    }
    
    void Emit_Starg(int iSlot)
    {        
    // @dogfood - handle bytes
        m_ilGenerator.Emit(OpCodes.Starg_S, (int) iSlot);
    }
    
    void Emit_Stloc(System.Reflection.Emit.LocalBuilder l)
    {
        m_ilGenerator.Emit(OpCodes.Stloc_S, l);    
    }
    
    // Emit the proper load-indirect opcode, depending on our type
    void Emit_Ldi(System.Type t)
    {
        if (t== typeof(int) || t.IsEnum)
        {
            m_ilGenerator.Emit(OpCodes.Ldind_I4);
        } 
        
        else if (t == typeof(char))
        {
            m_ilGenerator.Emit(OpCodes.Ldind_U2);        
        }
        
        else if (t.IsValueType)
        {
            m_ilGenerator.Emit(OpCodes.Ldobj, t);
        } 
        else 
        {
            m_ilGenerator.Emit(OpCodes.Ldind_Ref);
        }                
    }
    
    // emit proper store-indirect opcode
    void Emit_Sti(System.Type t)
    {               
        if (t == typeof(int) || t.IsEnum)
        {
            m_ilGenerator.Emit(OpCodes.Stind_I4);
        } 
        
        else if (t == typeof(char))
        {
            m_ilGenerator.Emit(OpCodes.Stind_I2);        
        }
        else if (t.IsValueType)
        {
            m_ilGenerator.Emit(OpCodes.Stobj, t);
        } 
        else 
        {
            m_ilGenerator.Emit(OpCodes.Stind_Ref);            
        }    
    }
    
    // Emit the proper Stelem flavor, depending on type
    void Emit_Stelem(System.Type tElem)
    {        
        if ((tElem == typeof(int)) || tElem.IsEnum)
        {
            m_ilGenerator.Emit(OpCodes.Stelem_I4);            
        } 
        
        else if (tElem == typeof(char))
        {
            m_ilGenerator.Emit(OpCodes.Stelem_I2);
        } 
        
        else 
        {
            Debug.Assert(!tElem.IsValueType, "Woah! Stelem for structs? Is that possible?");
            m_ilGenerator.Emit(OpCodes.Stelem_Ref);
        }
    }
    
    void Emit_Ldelem(System.Type tElem)
    {
        if ((tElem == typeof(int)) || tElem.IsEnum)
        {
            m_ilGenerator.Emit(OpCodes.Ldelem_I4);
        } 
        
        else if (tElem == typeof(char))
        {
            m_ilGenerator.Emit(OpCodes.Ldelem_U2);
        }
        else if (tElem.IsValueType)
        {
            m_ilGenerator.Emit(OpCodes.Ldelema, tElem);
            m_ilGenerator.Emit(OpCodes.Ldobj, tElem);
        } else
        {
            Debug.Assert(!tElem.IsValueType);
            m_ilGenerator.Emit(OpCodes.Ldelem_Ref);
        }
    }
    
    /***************************************************************************\
    * 
    * EmitCodeGen.GenerateBoxable
    * 
    * If we're generating a value type and it will be assigned to an object,
    * then we need to box it. This is used with RHS expressions.
    \**************************************************************************/
    public void
        GenerateBoxable(
        AST.Exp exp,
        System.Type tTarget
        )
    {        
        Debug.Assert(tTarget != null);

        System.Type tSource = exp.CLRType;

        exp.GenerateAsRight(this);
    
        // Check if we need to box.
        // Null expressions don't have a clr type. But they're not value
        // types so they don't have to be boxed.        
        if (tSource != null)
        {
            // Strip off references to look at base types
            if (tSource.IsByRef)
                tSource = tSource.GetElementType();
            if (tTarget.IsByRef)
                tTarget = tTarget.GetElementType();                
                
                
            if (tSource.IsValueType && !tTarget.IsValueType)
                m_ilGenerator.Emit(OpCodes.Box, tSource);
        } 
        else 
        {
            // Make sure this really is a null and not just an unresolved type
            // Note that ArgExp can be null, but can't be boxed. 
            Debug.Assert(AST.Exp.CanBeNullType(exp));
        }

    }
    
#endregion

#region Generate for Decls
    /***************************************************************************\
    *
    * EmitCodeGen.Generate
    *
    * Generate() recursively generates the program defined by the given node.
    *
    \***************************************************************************/

    public void
    Generate(
        AST.ProgramDecl nodeProgram)
    {
        // Generate all types.      
        Log.WriteLine(Log.LF.CodeGen, "***Generate bodies for all types");
        AST.TypeDeclBase [] al = nodeProgram.Classes;
        foreach (AST.TypeDeclBase t in al)
        {
            t.GenerateType(this);
        } 
        
        Log.WriteLine(Log.LF.CodeGen, "***Finished generating bodies for types. About to call CreateType()");
        
        // Now that the bodies have all been generating, the final thing we 
        // need to do is 'bless' all the types. Do this by calling CreateType()
        // on everything. 
        // We have to separate the CreateType phase from the GenerateBody
        // because CreateType may have to call itself recursively, and so
        // we'll need all the bodies to be created.
        foreach (AST.TypeDeclBase t in al)
        {
            TypeBuilder bld = (TypeBuilder) t.CLRType;
            Debug.Assert(bld != null);
            
            CreateType(bld);
        }        
    }

    /***************************************************************************\
    *
    * EmitCodeGen.Generate
    *
    * Generate() recursively generates the class defined by the given node.
    *
    \***************************************************************************/
    public void
        GenerateEnum(AST.EnumDecl node)
    {
        
        // Reflection-Emit requires that we 'bless' the enum via CreateType()
#if Bug_In_EnumBuilder
        TypeBuilder bld = (TypeBuilder) node.Symbol.CLRType;
#else
        EnumBuilder bld = (EnumBuilder) node.Symbol.CLRType;
#endif        
    }

    // ...
    // Account for another emit/loader bug. The type resolve event only give us
    // the short name. So keep a stack to get the full context.
    // When this bug is fixed, get rid of this variable.
    System.Collections.Stack m_CreateTypeStack = new System.Collections.Stack();


    //-----------------------------------------------------------------------------
    // Finalize the type and return the baked instance. This should never
    // return null. This can be called recursively.
    // We only bake a type once.
    //-----------------------------------------------------------------------------
    System.Type CreateType(TypeBuilder bld)
    {   
        string stName = bld.FullName;     
        
        // This should never throw an exception, but we catch it for debugging purposes.
        System.Type typeNewClass = null;
        
        // Since this is recursive, we may have already created the type. So check
        #if true       
        Type tCheck = ModuleBuilder_GetType(m_bldModule, stName);
        if (!(tCheck is TypeBuilder))
        {
            Log.WriteLine(Log.LF.CodeGen, "'{0}' already created..", stName);
            return typeNewClass;
        }
        #endif
                
        try
        {            
            Log.WriteLine(Log.LF.CodeGen, "About to call CreateType() for '{0}'", stName);
            
            // This stack is a bad hack to deal with a stupid Reflection-emit bug.            
            m_CreateTypeStack.Push(bld.FullName);            
            
            // This may fire a TypeResolve event which may turn around and call CreateType() again            
            typeNewClass = bld.CreateType();
            
            string s = (string) m_CreateTypeStack.Pop();
            Debug.Assert(s == bld.FullName);
            
            Log.WriteLine(Log.LF.CodeGen, "Type '{0}' fully created", stName);
        }
        
        catch(System.Exception e)
        {
            // Should never happen.
            // A very common cause for this failure is an bug in blue where
            // we fail to put an implied 'virtual' modifier on a method.Then the method doesn't
            // match in interface mapping and it looks like it wasn't implemented.
            Log.WriteLine(Log.LF.CodeGen, "CreateType() failed on '{0}' with exception:{1}", stName, e);
            throw;
        } 
        
        Debug.Assert(typeNewClass != null);
        Debug.Assert(!(typeNewClass is TypeBuilder));
        return typeNewClass;
    }


    /***************************************************************************\
    *
    * EmitCodeGen.Generate
    *
    * Generate() recursively generates the class defined by the given node.
    *
    \***************************************************************************/

    public void
    GenerateClass(
        AST.ClassDecl nodeClass)
    {
        //
        // Determine information about the base class:
        // - If the base-class is not already generated, need to generate it now.
        // - Get the System.Type of the base class.
        //
        string stName = nodeClass.Symbol.FullName;
        Log.WriteLine(Log.LF.CodeGen, "Begin generating class '{0}' [", stName);

        //
        // Begin the new class definition.
        //
                
        // Set the current class builder        
        TypeBuilder bldClass = nodeClass.Symbol.CLRType as TypeBuilder;
        Debug.Assert(bldClass != null);
        
        
        // Set the debugger document
        SetCurrentDebugDocument(nodeClass.Location);
        
        //
        // Generate the member methods.
        //

        if (!nodeClass.IsInterface)
        {
            AST.MethodDecl [] al = nodeClass.Methods;
            foreach (AST.MethodDecl nodeMethod in al)
            {
                if (!nodeMethod.Mods.IsAbstract) 
                {
                    Generate(nodeMethod);
                }
            }
            
            foreach (AST.PropertyDecl nodeProp in nodeClass.Properties)
            {
                Generate(nodeProp);
            }
        }

        Log.WriteLine(Log.LF.CodeGen, "] end body for '{0}'", stName);
        //
        // End the class definition.
        //

        /*            
        // This may catch a lot of problems (because it invokes the loader). 
        Type typeNewClass = null;
        
        try
        {   
            Log.WriteLine(Log.LF.CodeGen, "] About to call CreateType() on '{0}'", stName);
            typeNewClass = bldClass.CreateType();
            Log.WriteLine(Log.LF.CodeGen, "Type '{0}' fully created", stName);
        }
        catch(System.Exception e)
        {
            Log.WriteLine(Log.LF.CodeGen, "CreateType() failed on '{0}' with exception:{1}", stName, e);            
            throw;
        }
        Debug.Assert(typeNewClass != null, "Must have successfully created new class");
        
        */
        //m_alClasses.Add(typeNewClass);
        m_alClasses.Add(bldClass);

        //m_bldClass = null;
    }

    /***************************************************************************\
    *
    * EmitCodeGen.Generate
    *
    * Generate() recursively generates the method defined by the given node.
    *
    \***************************************************************************/
    public void
    Generate(
        AST.PropertyDecl nodeProp
    )
    {
        nodeProp.Generate(this);    
    }

    /***************************************************************************\
    *
    * EmitCodeGen.Generate
    *
    * Generate() recursively generates the method defined by the given node.
    *
    \***************************************************************************/

    public void
    Generate(
        AST.MethodDecl nodeMethod)
    {
            
        // Delegate impls have no body....
        
        if (AST.DelegateDecl.IsDelegate(nodeMethod.Symbol.SymbolClass.CLRType))
        {                        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -