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);
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)); }