public FunctionGenerator() { this.currentFunction = null; this.currentBreak = null; this.currentContinue = null; this.currentExceptionContext = null; this.builder = new BlockBuilder(); }
public CatchStatement(Expression exceptionType, string name, AstNode children, TokenPosition position) : base(children, position) { SetName(name); this.exceptionType = exceptionType; this.context = null; this.variable = null; }
public ExceptionContext(ExceptionContext parentContext) { // Store parent-child relation. this.parentContext = parentContext; this.parentFunction = parentContext.parentFunction; parentContext.children.Add(this); module = parentFunction.GetModule(); // Initialize more variables. this.children = new List<ExceptionContext> (); this.blocks = new List<BasicBlock> (); this.handlers = new List<Handler> (); this.cleanup = null; }
protected Function(ChelaModule module) : base(module) { this.name = string.Empty; this.flags = MemberFlags.Default; this.parentScope = null; this.basicBlocks = new List<BasicBlock> (); this.lexicalScopes = new List<LexicalScope>(); this.locals = new List<LocalVariable> (); this.position = null; this.exceptionContext = null; this.returnBlock = null; this.returningVar = null; this.returnValueVar = null; this.genericPrototype = GenericPrototype.Empty; this.arguments = null; }
public ExceptionContext(Function parentFunction) { // Store parent-child relation. this.parentContext = null; this.parentFunction = parentFunction; module = parentFunction.GetModule(); if(parentFunction.exceptionContext != null) throw new ModuleException("A function only can have one (toplevel) exception context."); parentFunction.exceptionContext = this; // Initialize more variables. this.children = new List<ExceptionContext> (); this.blocks = new List<BasicBlock> (); this.handlers = new List<Handler> (); this.cleanup = null; }
public void SetContext(ExceptionContext context) { this.context = context; }
public FinallyStatement(AstNode children, TokenPosition position) : base(position) { this.children = children; this.context = null; }
private int CountExceptionContexts(ExceptionContext context) { int ret = context.GetChildrenCount(); foreach(ExceptionContext subcontext in context.GetChildren()) ret += CountExceptionContexts(subcontext); return ret; }
internal void SwapExceptionContexts(Function other) { // Make sure the other end also takes my exception context. ExceptionContext newContext = other.exceptionContext; if(exceptionContext != null) { other.exceptionContext = null; other.SwapExceptionContexts(this); } // Use the new exception context. exceptionContext = newContext; if(newContext != null) exceptionContext.UpdateParent(this); }
public override AstNode Visit(TryStatement node) { // Begin the node. builder.BeginNode(node); // Read the substatements. AstNode tryNode = node.GetTryStatement(); AstNode catchList = node.GetCatchList(); AstNode finalNode = node.GetFinallyStatement(); // Read the exception context. ExceptionContext context = node.GetContext(); // Create the finally block. BasicBlock finalBlock = null; if(finalNode != null) { finalBlock = CreateBasicBlock(); finalBlock.SetName("finally"); context.SetCleanup(finalBlock); } // Create the merge block. BasicBlock merge = finalBlock; if(merge == null) { merge = CreateBasicBlock(); merge.SetName("trymerge"); } // Store the old context. ExceptionContext oldContext = currentExceptionContext; currentExceptionContext = context; // Create the try block. BasicBlock tryBlock = CreateBasicBlock(); tryBlock.SetName("try"); builder.CreateJmp(tryBlock); builder.SetBlock(tryBlock); // Process the try statement. tryNode.Accept(this); // Jump to finally/merge. bool tryReturn = builder.IsLastTerminator(); if(!builder.IsLastTerminator()) builder.CreateJmp(merge); // Restore the context, visit the catch list. currentExceptionContext = oldContext; AstNode catchNode = catchList; while(catchNode != null) { // Visit it. catchNode.Accept(this); // Jump to finally/merge. if(!builder.IsLastTerminator()) builder.CreateJmp(merge); // TODO: Avoid "duplicated" catches. catchNode = catchNode.GetNext(); } // Visit the finally statement if(finalNode != null) { // Generate the finally block. builder.SetBlock(finalBlock); // Visit it. finalNode.Accept(this); // Jump/resume to merge. if(builder.IsLastTerminator()) Error(finalNode, "finally cannot return."); // Create propagate return block. BasicBlock propRet = CreateBasicBlock(); propRet.SetName("propRet"); builder.CreateJumpResume(propRet); builder.SetBlock(propRet); // Find the parent return. BasicBlock parentRetBlock = null; ExceptionContext parentContext = context.GetParentContext(); while(parentContext != null) { parentRetBlock = parentContext.GetCleanup(); if(parentRetBlock != null) break; parentContext = parentContext.GetParentContext(); } // Couldn't find a parent cleanup, return. if(parentRetBlock == null) parentRetBlock = currentFunction.ReturnBlock; // If try returns and theres not catch, just return. if(tryReturn && catchNode == null) { builder.CreateJmp(parentRetBlock); AstNode next = node.GetNext(); if(next != null) Warning(next, "unreachable code detected."); node.SetNext(null); } else { // Merge with the other blocks. merge = CreateBasicBlock(); merge.SetName("trymerge"); // Return/finally or merge. builder.CreateLoadLocal(currentFunction.ReturningVar); builder.CreateBr(parentRetBlock, merge); } } // Remove unused code. if(merge.GetPredsCount() == 0) { if(node.GetNext() != null) Warning(node, "detected unreachable code at {0}", node.GetNext().GetPosition()); node.SetNext(null); merge.Destroy(); } else { // Continue without try. builder.SetBlock(merge); } return builder.EndNode(); }
public override AstNode Visit(TryStatement node) { // Read the substatements. AstNode tryNode = node.GetTryStatement(); AstNode catchList = node.GetCatchList(); AstNode finalNode = node.GetFinallyStatement(); // Create the exception context. ExceptionContext context; if(currentExceptionContext != null) context = new ExceptionContext(currentExceptionContext); else context = new ExceptionContext(currentFunction); node.SetContext(context); // Store the old context and process the try statement. ExceptionContext oldContext = currentExceptionContext; currentExceptionContext = context; tryNode.Accept(this); // Restore the context, visit the catch list. currentExceptionContext = oldContext; AstNode catchNode = catchList; while(catchNode != null) { // Set the exception context. CatchStatement catchStmnt = (CatchStatement)catchNode; catchStmnt.SetContext(context); // Visit it. catchStmnt.Accept(this); // TODO: Avoid "duplicated" catches. catchNode = catchNode.GetNext(); } // Visit the finally statement if(finalNode != null) { // Set the exception context. FinallyStatement finalStmnt = (FinallyStatement)finalNode; finalStmnt.SetContext(context); // Visit it. finalStmnt.Accept(this); } return node; }
public FunctionSemantic() { currentExceptionContext = null; currentSwitch = null; }