Exemplo n.º 1
0
 public CaseLabel(Expression constant, AstNode children, TokenPosition position)
     : base(position)
 {
     this.constant = constant;
     this.children = children;
     this.block = null;
 }
Exemplo n.º 2
0
 public FunctionGenerator()
 {
     this.currentFunction = null;
     this.currentBreak = null;
     this.currentContinue = null;
     this.currentExceptionContext = null;
     this.builder = new BlockBuilder();
 }
Exemplo n.º 3
0
        public void AddSuccessor(BasicBlock successor)
        {
            if(successors == null)
                successors = new List<BasicBlock> ();

            successors.Add(successor);
            successor.AddPredecesor(this);
        }
Exemplo n.º 4
0
        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;
        }
Exemplo n.º 5
0
        public void AddCatch(Structure exception, BasicBlock block)
        {
            foreach(Handler h in handlers)
            {
                if(h.exception == exception)
                    throw new ModuleException("Exception is already handled.");
            }

            // Store.
            Handler ha = new Handler();
            ha.exception = exception;
            ha.handler = block;
            handlers.Add(ha);
        }
Exemplo n.º 6
0
        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;
        }
Exemplo n.º 7
0
 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;
 }
Exemplo n.º 8
0
        public override AstNode Visit(SwitchStatement node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Process the switch expression.
            Expression switchExpr = node.GetConstant();
            switchExpr.Accept(this);

            // Perform coercion.
            IChelaType switchType = switchExpr.GetNodeType();
            IChelaType coercionType = node.GetCoercionType();
            if(switchType != coercionType)
                Cast(node, switchExpr.GetNodeValue(), switchType, coercionType);

            // Create the merge block.
            BasicBlock merge = CreateBasicBlock();
            merge.SetName("smerge");

            // Store the old break.
            BasicBlock oldBreak = currentBreak;
            currentBreak = merge;

            // Initialize the default block to the merge.
            BasicBlock defaultBlock = merge;

            // Get the cases dictionary.
            IDictionary<ConstantValue, CaseLabel> caseDictionary = node.CaseDictionary;

            // Create the jump table.
            int tableSize = caseDictionary.Count + 1;
            int[] constants = new int[tableSize];
            BasicBlock[] blocks = new BasicBlock[tableSize];

            // The first element is always the default block.
            int i = 0;
            constants[i] = -1;
            blocks[i] = defaultBlock; ++i;

            // Add the other elements.
            BasicBlock caseBlock = null;
            CaseLabel label = (CaseLabel)node.GetCases();
            while(label != null)
            {
                // Create the label block.
                if(caseBlock == null)
                {
                    caseBlock = CreateBasicBlock();
                    caseBlock.SetName("caseBlock");
                }

                // Set the label block.
                label.SetBlock(caseBlock);

                // Store the default block.
                if(label.GetConstant() == null)
                {
                    defaultBlock = caseBlock;
                    blocks[0] = caseBlock;
                }
                else
                {
                    // Append it to the jump table.
                    Expression caseExpr = label.GetConstant();
                    ConstantValue caseConstant = (ConstantValue)caseExpr.GetNodeValue();
                    constants[i] = caseConstant.GetIntValue();
                    blocks[i] = caseBlock;
                    ++i;
                }

                // Create a new block if the last case wasn't empty.
                if(label.GetChildren() != null)
                    caseBlock = null;

                // Process the next label.
                label = (CaseLabel)label.GetNext();
            }

            // Perform the switch.
            BasicBlock switchBlock = builder.GetBlock();
            builder.CreateSwitch(constants, blocks);

            // Generate the cases blocks.
            VisitList(node.GetCases());

            // Continue with the normal flow.
            currentBreak = oldBreak;

            // Remove the merge block if its unreachable.
            if(merge.GetPredsCount() == 0)
            {
                builder.SetBlock(switchBlock);
                merge.Destroy();
                if(node.GetNext() != null)
                    Warning(node.GetNext(), "detected unreachable code.");
                node.SetNext(null);
            }
            else
            {
                builder.SetBlock(merge);
            }

            return builder.EndNode();
        }
Exemplo n.º 9
0
        private Method CreateTrivialConstructor(Structure building, Structure buildingInstance)
        {
            // Create the constructor function type.
            FunctionType type = FunctionType.Create(ChelaType.GetVoidType(),
                new IChelaType[]{ReferenceType.Create(buildingInstance)}, false);

            // Create the constructor.
            Method ctor = new Method(".ctor", MemberFlags.Public | MemberFlags.Constructor, building);
            ctor.SetFunctionType(type);
            building.AddFunction(".ctor", ctor);

            // Create the constructor block.
            BasicBlock top = new BasicBlock(ctor);
            top.SetName("top");
            top.Append(new Instruction(OpCode.RetVoid, null));

            return ctor;
        }
Exemplo n.º 10
0
        private void PrepareReturning(AstNode where, Function function, LexicalScope scope)
        {
            // Get the definition node and check for generator.
            FunctionDefinition defNode = function.DefinitionNode;
            bool isGenerator = false;
            if(defNode != null)
                isGenerator = defNode.IsGenerator;

            // Use standard return.
            if(function.GetExceptionContext() == null && !isGenerator)
                return;

            // Create the return block.
            BasicBlock returnBlock = new BasicBlock(function);
            returnBlock.SetName("retBlock");
            function.ReturnBlock = returnBlock;

            // Create the return value local.
            FunctionType functionType = function.GetFunctionType();
            IChelaType retType = functionType.GetReturnType();
            if(retType != ChelaType.GetVoidType() && !isGenerator)
                function.ReturnValueVar = new LocalVariable(GenSym() + "_retval", scope, retType);

            // Create the is returning flag.
            function.ReturningVar = new LocalVariable(GenSym() + "_isret", scope, ChelaType.GetBoolType(), isGenerator);
            function.ReturningVar.Type = LocalType.Return;

            // Create the field for generators.
            if(isGenerator)
            {
                FieldVariable returningField = new FieldVariable("returning", MemberFlags.Private,
                    ChelaType.GetBoolType(), defNode.GeneratorClass);
                defNode.GeneratorClass.AddField(returningField);
                function.ReturningVar.ActualVariable = returningField;
            }

            // Initializer the returning flag to false.
            builder.CreateLoadBool(false);
            PerformAssignment(where, function.ReturningVar);
        }
Exemplo n.º 11
0
        private void CreateGenerator_Reset(FunctionDefinition node)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(ChelaType.GetVoidType(),
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method("Reset", MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            genClass.AddFunction("Reset", method);

            // Create the top block.
            BasicBlock top = new BasicBlock(method);
            builder.SetBlock(top);

            // Throw an exception.
            Class excpt = (Class)ExtractClass(node, currentModule.GetLangMember("InvalidOperationException"));
            builder.CreateLoadString("IEnumerator.Reset cannot be called in generators.");
            builder.CreateNewObject(excpt, GetExceptionCtor(node, excpt), 1);
            builder.CreateThrow();
        }
Exemplo n.º 12
0
        private void CreateStaticConstructor(AstNode node, Namespace space)
        {
            // Check for a previous definition.
            if(space.GetStaticConstructor() != null || space.GetGlobalInitializations() == null)
                return;

            // Get the static initialization fields.
            List<FieldDeclaration> staticInitedField = new List<FieldDeclaration> ();
            bool isUnsafe = false;
            foreach(FieldDeclaration decl in space.GetGlobalInitializations())
            {
                Variable variable = decl.GetVariable();
                if(variable.IsStatic())
                {
                    staticInitedField.Add(decl);
                    if(variable.IsUnsafe())
                        isUnsafe = true;
                }
            }

            // If there aren't field to initialize, don't create the static constructor.
            if(staticInitedField.Count == 0)
                return;

            // Create the static constructor function type.
            FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType());

            // Create the constructor method.
            MemberFlags flags = MemberFlags.StaticConstructor;
            if(isUnsafe)
                flags |= MemberFlags.Unsafe;
            Function constructor = new Function("<sctor>", flags, space);
            constructor.SetFunctionType(ctorType);

            // Store it.
            space.AddMember(constructor);

            // Create the constructor scope.
            LexicalScope ctorScope = CreateLexicalScope(node, constructor);
            PushScope(ctorScope);

            // Create the top basic block.
            BasicBlock topBlock = new BasicBlock(constructor);
            builder.SetBlock(topBlock);

            // Initialize the static fields.
            GenerateStaticFieldInitializations(null, staticInitedField);

            // Restore the scope.
            PopScope();

            // Return void.
            builder.CreateRetVoid();
        }
Exemplo n.º 13
0
 public void SetBlock(BasicBlock block)
 {
     this.block = block;
 }
Exemplo n.º 14
0
 public void SetCleanup(BasicBlock block)
 {
     this.cleanup = block;
 }
Exemplo n.º 15
0
 private void AddPredecesor(BasicBlock pred)
 {
     if(preds == null)
         preds = new List<BasicBlock> ();
     preds.Add(pred);
 }
Exemplo n.º 16
0
 public void SetBlock(BasicBlock block)
 {
     // Set the block.
     this.currentBlock = block;
 }
Exemplo n.º 17
0
        private void CreateDefaultConstructor(StructDefinition node)
        {
            // Get the structure, and the default constructor.
            Structure building = node.GetStructure();
            Method constructor = node.GetDefaultConstructor();

            // Ignore structures without a default constructor.
            if(constructor == null)
                return;

            // Crete the self scope.
            LexicalScope selfScope = CreateLexicalScope(node, constructor);
            new ArgumentVariable(0, "this", selfScope, ReferenceType.Create(building));
            PushScope(selfScope);

            // Create the top basic block.
            BasicBlock topBlock = new BasicBlock(constructor);
            builder.SetBlock(topBlock);

            // Add implicit construction expressions.
            CreateImplicitBaseConstructor(node, constructor);

            // Initialize some field.
            GenerateFieldInitializations(node, building);

            // Restore the scope.
            PopScope();

            // Return void.
            builder.CreateRetVoid();
        }
Exemplo n.º 18
0
 internal int AddBlock(BasicBlock block)
 {
     int ret = this.basicBlocks.Count;
     this.basicBlocks.Add(block);
     return ret;
 }
Exemplo n.º 19
0
 private BasicBlock CreateBasicBlock()
 {
     BasicBlock ret = new BasicBlock(currentFunction);
     ret.IsUnsafe = IsUnsafe;
     if(currentExceptionContext != null)
         currentExceptionContext.AddBlock(ret);
     return ret;
 }
Exemplo n.º 20
0
        public void RemoveBlock(BasicBlock block)
        {
            // Remove it from my blocks.
            for(int i = 0; i < blocks.Count; ++i)
            {
                if(blocks[i] == block)
                {
                    blocks.RemoveAt(i);
                    break;
                }
            }

            // Remove it from my handlers.
            for(int i = 0; i < handlers.Count; ++i)
            {
                Handler h = (Handler)handlers[i];
                if(h.handler == block)
                {
                    handlers.RemoveAt(i);
                    break;
                }
            }

            // Remove it from my cleanup.
            if(cleanup == block)
                cleanup = null;

            // Remove it from my children.
            foreach(ExceptionContext child in children)
                child.RemoveBlock(block);
        }
Exemplo n.º 21
0
        public override AstNode Visit(ForStatement node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Get the for elements.
            AstNode decl = node.GetDecls();
            AstNode cond = node.GetCondition();
            AstNode incr = node.GetIncr();

            // Write the declaration.
            if(decl != null)
                decl.Accept(this);

            // Create the basics blocks.
            BasicBlock forStart = CreateBasicBlock();
            BasicBlock forEnd = CreateBasicBlock();
            BasicBlock forBreak = CreateBasicBlock();
            BasicBlock forCond = forStart;

            // Set the blocks names.
            forStart.SetName("for_start");
            forEnd.SetName("for_end");
            forBreak.SetName("for_break");

            // Store and update the break and continue points.
            BasicBlock oldBreak = currentBreak;
            BasicBlock oldContinue = currentContinue;
            currentBreak = forBreak;
            currentContinue = forEnd;

            // Write the condition.
            if(cond != null)
            {
                // Create the condition block.
                forCond = CreateBasicBlock();
                forCond.SetName("for_cond");

                // Jump into the condition.
                builder.CreateJmp(forCond);
                builder.SetBlock(forCond);

                // Write the condition.
                cond.Accept(this);

                // Cast the condition.
                IChelaType condType = cond.GetNodeType();
                if(condType != ChelaType.GetBoolType())
                    Cast(node, cond.GetNodeValue(), condType, ChelaType.GetBoolType());

                // Perform the conditional branch.
                builder.CreateBr(forStart, forBreak);
            }
            else
            {
                // Jump into the beginning of the loop.
                builder.CreateJmp(forStart);
            }

            // Write the loop content.
            builder.SetBlock(forStart);
            VisitList(node.GetChildren());

            // Branch into the loop end.
            if(!builder.IsLastTerminator())
                builder.CreateJmp(forEnd);

            // Write the for end.
            builder.SetBlock(forEnd);

            // Write the increment.
            if(incr != null)
                incr.Accept(this);

            // Branch into the condition.
            if(!builder.IsLastTerminator())
                builder.CreateJmp(forCond);

            // Continue with the rest of the program.
            builder.SetBlock(forBreak);

            // Restore the break and continue point.
            currentBreak = oldBreak;
            currentContinue = oldContinue;

            return builder.EndNode();
        }
Exemplo n.º 22
0
        public override AstNode Visit(DoWhileStatement node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Get the condition and the job.
            Expression cond = node.GetCondition();
            AstNode job = node.GetJob();

            // Create the basic blocks.
            BasicBlock condBlock = CreateBasicBlock();
            BasicBlock contentBlock = CreateBasicBlock();
            BasicBlock endBlock = CreateBasicBlock();

            // Set the blocks names.
            condBlock.SetName("cond");
            contentBlock.SetName("content");
            endBlock.SetName("end");

            // Store the old break and continue.
            BasicBlock oldBreak = currentBreak;
            BasicBlock oldContinue = currentContinue;

            // Set the new break and continue.
            currentBreak = endBlock;
            currentContinue = condBlock;

            // Branch into the content.
            builder.CreateJmp(contentBlock);

            // Write the content.
            builder.SetBlock(contentBlock);
            job.Accept(this);

            // Branch into the condition.
            if(!builder.IsLastTerminator())
                builder.CreateJmp(condBlock);

            // Write the condition.
            builder.SetBlock(condBlock);
            cond.Accept(this);

            // Cast the condition.
            IChelaType condType = cond.GetNodeType();
            if(condType != ChelaType.GetBoolType())
                Cast(node, cond.GetNodeValue(), condType, ChelaType.GetBoolType());

            // Close the loop.
            builder.CreateBr(contentBlock, endBlock);

            // Continue with the normal flow.
            builder.SetBlock(endBlock);

            // Restore the break and continue blocks.
            currentBreak = oldBreak;
            currentContinue = oldContinue;

            return builder.EndNode();
        }
Exemplo n.º 23
0
        private void CreateGenerator_GetEnumerator(FunctionDefinition node, Structure enumeratorType, bool generic)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Use the GetEnumerator name for the most specific version.
            string name = "GetEnumerator";
            Function contract = null;
            if(!generic && node.IsGenericIterator)
            {
                name = GenSym();
                contract = FindFirstConstract(currentModule.GetEnumerableIface(), "GetEnumerator");
            }

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(ReferenceType.Create(enumeratorType),
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method(name, MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            genClass.AddFunction(name, method);

            // Set the explicit contract.
            if(contract != null)
                method.SetExplicitContract(contract);

            // Create the method block.
            BasicBlock block = new BasicBlock(method);
            block.SetName("top");

            // Return this.
            builder.SetBlock(block);
            builder.CreateLoadArg(0);
            builder.CreateRet();
        }
Exemplo n.º 24
0
 public void CreateBr(BasicBlock trueDest, BasicBlock falseDest)
 {
     AppendInst2(OpCode.Br, trueDest, falseDest);
     currentBlock.AddSuccessor(trueDest);
     currentBlock.AddSuccessor(falseDest);
 }
Exemplo n.º 25
0
        private Function CreateGenerator_MoveNext(FunctionDefinition node)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(ChelaType.GetBoolType(),
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method("MoveNext", MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            method.DefinitionNode = node;
            genClass.AddFunction("MoveNext", method);

            // Swap the exception contexts.
            method.SwapExceptionContexts(currentFunction);

            // Store the old function.
            Function oldFunction = currentFunction;
            currentFunction = method;

            // Create the jump table block.
            BasicBlock jmpBlock = CreateBasicBlock();
            jmpBlock.SetName("jmp");

            // Generate the main code.
            BasicBlock topBlock = CreateBasicBlock();
            topBlock.SetName("top");
            builder.SetBlock(topBlock);

            // Prepare returning.
            LexicalScope topScope = (LexicalScope) node.GetScope();
            PrepareReturning(node, currentFunction, topScope);

            // Create the function body.
            VisitList(node.GetChildren());

            // Finish returning.
            FinishReturn(node, currentFunction);

            // Create the state jump table.
            builder.SetBlock(jmpBlock);

            // Load the current state.
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.GeneratorState);

            // Build the jump table.
            int numstates = node.Yields.Count*2+3;
            int[] stateConstants = new int[numstates];
            BasicBlock[] stateEntries = new BasicBlock[numstates];

            // The default case is return.
            stateConstants[0] = -1;
            stateEntries[0] = currentFunction.ReturnBlock;

            // The first state is the top block.
            stateConstants[1] = 0;
            stateEntries[1] = topBlock;

            // The second state is the return block.
            stateConstants[2] = 1;
            stateEntries[2] = currentFunction.ReturnBlock;

            // The next states are the yield merges followed by yield disposes.
            for(int i = 0; i < node.Yields.Count; ++i)
            {
                ReturnStatement yieldStmnt = node.Yields[i];

                // Emit the merge state.
                int stateId = i*2+2;
                int entryIndex = stateId+1;
                stateConstants[entryIndex] = stateId;
                stateEntries[entryIndex] = yieldStmnt.MergeBlock;

                // Emit the dispose state.
                stateConstants[entryIndex+1] = stateId+1;
                stateEntries[entryIndex+1] = yieldStmnt.DisposeBlock;
            }

            builder.CreateSwitch(stateConstants, stateEntries);

            // Restore the old function.
            currentFunction = oldFunction;

            return method;
        }
Exemplo n.º 26
0
        private void CreateDefaultStaticConstructor(StructDefinition node)
        {
            // Get the structure.
            Structure building = node.GetStructure();

            // Check for an user defined constructor.
            if(building.GetStaticConstructor() != null)
                return;

            // Get the static initialization fields.
            List<FieldDeclaration> staticInitedField = new List<FieldDeclaration> ();
            bool isUnsafe = false;
            foreach(FieldDeclaration decl in building.GetFieldInitializations())
            {
                Variable variable = decl.GetVariable();
                if(variable.IsStatic())
                {
                    staticInitedField.Add(decl);
                    if(variable.IsUnsafe())
                        isUnsafe = true;
                }
            }

            // If there aren't field to initialize, don't create the static constructor.
            if(staticInitedField.Count == 0)
                return;

            // Begin the node.
            builder.BeginNode(node);

            // Create the static constructor function type.
            FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType());

            // Create the constructor method.
            MemberFlags flags = MemberFlags.StaticConstructor;
            if(isUnsafe)
                flags |= MemberFlags.Unsafe;
            Method constructor = new Method("<sctor>", flags, building);
            constructor.SetFunctionType(ctorType);

            // Store it.
            building.AddFunction("<sctor>", constructor);

            // Create the constructor scope.
            LexicalScope ctorScope = CreateLexicalScope(node, constructor);
            PushScope(ctorScope);

            // Create the top basic block.
            BasicBlock topBlock = new BasicBlock(constructor);
            builder.SetBlock(topBlock);

            // Initialize the static fields.
            GenerateStaticFieldInitializations(node, staticInitedField);

            // Restore the scope.
            PopScope();

            // Return void.
            builder.CreateRetVoid();

            // End the node.
            builder.EndNode();
        }
Exemplo n.º 27
0
 public void AddBlock(BasicBlock block)
 {
     blocks.Add(block);
 }
Exemplo n.º 28
0
        internal void RemoveBasicBlock(BasicBlock block)
        {
            // Displace the upper blocks.
            int numblocks = basicBlocks.Count;
            for(int i = block.blockIndex; i < numblocks-1; ++i)
            {
                BasicBlock next = (BasicBlock)basicBlocks[i+1];
                next.blockIndex = i;
                basicBlocks[i] = next;
            }

            // Remove the last block.
            basicBlocks.RemoveAt(numblocks-1);

            // Remove the block from the exception contexts
            if(exceptionContext != null)
                exceptionContext.RemoveBlock(block);
        }
Exemplo n.º 29
0
        private void CreateGenerator_Current(FunctionDefinition node, bool generic)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Use the get_Current name for the most specific version.
            string name = "get_Current";
            Function contract = null;
            if(!generic && node.IsGenericIterator)
            {
                name = GenSym();
                contract = FindFirstConstract(currentModule.GetEnumeratorIface(), "get_Current");
            }

            // Select the current type.
            IChelaType currentType = node.YieldType;
            if(!generic)
                currentType = ReferenceType.Create(currentModule.GetObjectClass());

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(currentType,
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method(name, MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            genClass.AddFunction(name, method);

            // Set the explicit contract.
            if(contract != null)
                method.SetExplicitContract(contract);

            // Create the method block.
            BasicBlock block = new BasicBlock(method);
            block.SetName("top");

            // Create the return and error blocks.
            BasicBlock retBlock = new BasicBlock(method);
            retBlock.SetName("ret");

            BasicBlock errorBlock = new BasicBlock(method);
            errorBlock.SetName("error");

            // Make sure reset was called before the first Current.
            builder.SetBlock(block);
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.GeneratorState);
            builder.CreateLoadInt32(0);
            builder.CreateCmpEQ();
            builder.CreateBr(errorBlock, retBlock);

            // Raise an error if reset wasn't called.
            builder.SetBlock(errorBlock);

            Class excpt = (Class)ExtractClass(node, currentModule.GetLangMember("InvalidOperationException"));
            builder.CreateLoadString("IEnumerator.MoveNext must be called before than IEnumerator.Current.");
            builder.CreateNewObject(excpt, GetExceptionCtor(node, excpt), 1);
            builder.CreateThrow();

            // Load the yielded value.
            builder.SetBlock(retBlock);
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.YieldedValue);

            // Cast the yielded value.
            Cast(node, null, node.YieldType, currentType);

            // Return.
            builder.CreateRet();
        }
Exemplo n.º 30
0
        private void CreateGenerator_Dispose(FunctionDefinition node, Function moveNext)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(ChelaType.GetVoidType(),
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method("Dispose", MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            genClass.AddFunction("Dispose", method);

            // Create the top block.
            BasicBlock top = new BasicBlock(method);
            builder.SetBlock(top);

            // Create the return and dispose blocks.
            BasicBlock justReturn = new BasicBlock(method);
            BasicBlock disposeAndReturn = new BasicBlock(method);

            // Load the current state.
            builder.CreateLoadArg(0);
            builder.CreateDup1();
            builder.CreateDup1();
            builder.CreateLoadField(node.GeneratorState);
            builder.CreateDup1();
            builder.CreateLoadInt32(1);
            builder.CreateCmpEQ();
            builder.CreateBr(justReturn, disposeAndReturn);

            // Dispose and return implementation.
            builder.SetBlock(disposeAndReturn);

            // Increase the state.
            builder.CreateLoadInt32(1);
            builder.CreateAdd();
            builder.CreateStoreField(node.GeneratorState);

            // Call move next.
            builder.CreateCall(moveNext, 1);
            builder.CreateRetVoid();

            // Just return implementation.
            builder.SetBlock(justReturn);
            builder.CreateRetVoid();
        }
Exemplo n.º 31
0
        private void EmitBasicBlockDebugInfo(ModuleWriter writer, BasicBlock block)
        {
            // Compute instructions subblocks.
            List <SubBlock> subBlocks = new List <SubBlock> ();
            TokenPosition   position  = NullPosition;
            int             start     = 0;
            int             index     = 0;

            foreach (Instruction inst in block.GetInstructions())
            {
                // Get the instruction position.
                TokenPosition instPos = inst.GetPosition();
                if (instPos == null)
                {
                    instPos = NullPosition;
                }

                if (instPos != position)
                {
                    // Create a sub block for the previous set.
                    if (index != 0)
                    {
                        SubBlock subBlock = new SubBlock();
                        subBlock.Position = position;
                        subBlock.Start    = (ushort)start;
                        subBlock.End      = (ushort)(index - 1);

                        // Store the sub block.
                        subBlocks.Add(subBlock);
                    }

                    // Store the start of the next subblock.
                    start    = index;
                    position = instPos;
                }

                // Increase the index.
                ++index;
            }

            // Create the last sub block.
            SubBlock lastSubBlock = new SubBlock();

            lastSubBlock.Position = position;
            lastSubBlock.Start    = (ushort)(start);
            lastSubBlock.End      = (ushort)(index - 1);

            // Store the sub block.
            subBlocks.Add(lastSubBlock);

            // Emit all of the sub blocks.
            ushort numSubs = (ushort)subBlocks.Count;

            writer.Write(numSubs);
            foreach (SubBlock subBlock in subBlocks)
            {
                writer.Write(subBlock.Start);
                writer.Write(subBlock.End);
                EmitPosition(writer, subBlock.Position);
            }
        }