Ejemplo n.º 1
0
        public override LLVMValueRef Emit(EmittingContext pContext)
        {
            pContext.EmitDebugLocation(this);

            if (!External)
            {
                System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(_name), "Method name cannot be blank");
                var func = pContext.StartMethod(_name, this);
                pContext.AddDeferredStatementExecution();
                pContext.Locals.AddScope();
                pContext.AddDebugScope(Span);

                //Method bodies are slightly special because we want all variables to be declared in their scope
                //Don't call Body.Emit because that starts a new scope and all our variables will be not declared for deferred statements
                foreach (var s in Body.Statements)
                {
                    if (!s.Deferred)
                    {
                        s.Emit(pContext);
                    }
                    else
                    {
                        pContext.AddDeferredStatement(s);
                    }
                }

                //Emit all deferred statements unless the return handled it for us
                var lastIsReturn = Utils.SyntaxHelper.LastStatementIsReturn(Body);
                if (!lastIsReturn)
                {
                    foreach (var s in pContext.GetDeferredStatements())
                    {
                        s.Emit(pContext);
                    }

                    //We want to dispose variables after deferred statements because
                    //then variables referenced in deferred statements will still be valid
                    BlockSyntax.BuildCallToDispose(pContext);

                    if (ReturnValues.Count == 0)
                    {
                        LLVM.BuildRetVoid(pContext.Builder);
                    }
                    else
                    {
                        //Return statements have been validated. It probably returned in some other block earlier.
                        //LLVM requires return statement so just return default
                        LLVM.BuildRet(pContext.Builder, SmallTypeCache.GetLLVMDefault(Type, pContext));
                    }
                }

                //End method
                pContext.RemoveDeferredStatementExecution();
                pContext.RemoveDebugScope();
                pContext.Locals.RemoveScope();
                pContext.FinishMethod(func);
                return(func);
            }

            return(default);
Ejemplo n.º 2
0
        public override LLVMValueRef Emit(EmittingContext pContext)
        {
            pContext.EmitDebugLocation(this);

            //Emit deferred statements right before return
            foreach (var s in pContext.GetDeferredStatements())
            {
                s.Emit(pContext);
            }

            //We want to dispose variables after deferred statements because
            //then variables referenced in deferred statements will still be valid
            BlockSyntax.BuildCallToDispose(pContext);

            if (Values.Count == 0)
            {
                return(LLVM.BuildRetVoid(pContext.Builder));
            }

            LLVMValueRef v;

            if (Values.Count == 1)
            {
                v = Values[0].Emit(pContext);
                Utils.LlvmHelper.LoadIfPointer(ref v, pContext);
            }
            else
            {
                //Allocate our tuple and set each field
                v = LLVM.BuildAlloca(pContext.Builder, SmallTypeCache.GetLLVMType(Type, pContext), "");
                for (int i = 0; i < Values.Count; i++)
                {
                    var location = LLVM.BuildInBoundsGEP(pContext.Builder, v, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(i) }, "");
                    var value    = Values[i].Emit(pContext);
                    Utils.LlvmHelper.LoadIfPointer(ref value, pContext);
                    LLVM.BuildStore(pContext.Builder, value, location);
                }
                v = LLVM.BuildLoad(pContext.Builder, v, "");
            }
            return(LLVM.BuildRet(pContext.Builder, v));
        }