// This constructor is only called for Preloading of assemblies and // precompilation of CodeBlockNode nodes in GraphUI for global language blocks - pratapa public CodeGen(ProtoLanguage.CompileStateTracker compileState) : base(compileState) { Validity.Assert(compileStateTracker.IsParsingPreloadedAssembly || compileStateTracker.IsParsingCodeBlockNode); classOffset = 0; // either of these should set the console to flood // ignoreRankCheck = false; emitReplicationGuide = false; astNodes = new List<AssociativeNode>(); globalInstanceProcList = new List<GlobalInstanceProc>(); setConstructorStartPC = false; // Re-use the existing procedureTable and symbolTable to access the built-in and predefined functions ProcedureTable procTable = compileStateTracker.CodeBlockList[0].procedureTable; codeBlock = BuildNewCodeBlock(procTable); // Remove global symbols from existing symbol table for subsequent run in Graph UI //SymbolTable sTable = core.CodeBlockList[0].symbolTable; //sTable.RemoveGlobalSymbols(); //codeBlock = core.CodeBlockList[0]; compilePass = ProtoCore.DSASM.AssociativeCompilePass.kClassName; // Bouncing to this language codeblock from a function should immediately set the first instruction as the entry point if (ProtoCore.DSASM.Constants.kGlobalScope != globalProcIndex) { isEntrySet = true; codeBlock.instrStream.entrypoint = 0; } nodeBuilder = new NodeBuilder(compileStateTracker); unPopulatedClasses = new Dictionary<int, ClassDeclNode>(); }
public CodeGen(ProtoLanguage.CompileStateTracker compileState, ProtoCore.DSASM.CodeBlock parentBlock = null) : base(compileState, parentBlock) { classOffset = 0; // either of these should set the console to flood // ignoreRankCheck = false; emitReplicationGuide = false; astNodes = new List<AssociativeNode>(); globalInstanceProcList = new List<GlobalInstanceProc>(); setConstructorStartPC = false; // Comment Jun: Get the codeblock to use for this codegenerator if (compileStateTracker.Options.IsDeltaExecution) { codeBlock = GetDeltaCompileCodeBlock(); pc = compileStateTracker.deltaCompileStartPC; } else { codeBlock = BuildNewCodeBlock(); } if (null == parentBlock) { if (!compileStateTracker.Options.IsDeltaExecution) { // This is a top level block compileStateTracker.CodeBlockList.Add(codeBlock); } } else { // TODO Jun: Handle nested codeblock here when we support scoping in the graph // This is a nested block // parentBlock == codeBlock happens when the core is in // delta exectuion and at the same time we create a dynamic // code block (e.g., inline condition) if (parentBlock == codeBlock) { codeBlock = BuildNewCodeBlock(); pc = 0; } parentBlock.children.Add(codeBlock); codeBlock.parent = parentBlock; } compileStateTracker.CompleteCodeBlockList.Add(codeBlock); compilePass = ProtoCore.DSASM.AssociativeCompilePass.kClassName; // Bouncing to this language codeblock from a function should immediately set the first instruction as the entry point if (ProtoCore.DSASM.Constants.kGlobalScope != globalProcIndex) { isEntrySet = true; codeBlock.instrStream.entrypoint = 0; } nodeBuilder = new NodeBuilder(compileStateTracker); unPopulatedClasses = new Dictionary<int, ClassDeclNode>(); // For sub code block, say in inline condition, do we need context? /* if (core.assocCodegen != null) { context = core.assocCodegen.context; } */ }
private int EmitExpressionInterpreter(ProtoCore.AST.Node codeBlockNode) { compileStateTracker.startPC = this.pc; compilePass = AssociativeCompilePass.kGlobalScope; ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode; ProtoCore.Type inferedType = new ProtoCore.Type(); globalClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex; globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope; // check if currently inside a function when the break was called if (compileStateTracker.DebugProps.DebugStackFrameContains(DebugProperties.StackFrameFlagOptions.FepRun)) { // Save the current scope for the expression interpreter globalClassIndex = compileStateTracker.watchClassScope = (int)compileStateTracker.Rmem.GetAtRelative(compileStateTracker.Rmem.GetStackIndex(ProtoCore.DSASM.StackFrame.kFrameIndexClass)).opdata; globalProcIndex = compileStateTracker.watchFunctionScope = (int)compileStateTracker.Rmem.GetAtRelative(compileStateTracker.Rmem.GetStackIndex(ProtoCore.DSASM.StackFrame.kFrameIndexFunction)).opdata; int functionBlock = (int)compileStateTracker.Rmem.GetAtRelative(compileStateTracker.Rmem.GetStackIndex(ProtoCore.DSASM.StackFrame.kFrameIndexFunctionBlock)).opdata; if (globalClassIndex != -1) localProcedure = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex]; else { // TODO: to investigate whethter to use the table under executable or in core.FuncTable - Randy, Jun localProcedure = compileStateTracker.DSExecutable.procedureTable[functionBlock].procList[globalProcIndex]; } } foreach (AssociativeNode node in codeblock.Body) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; DfsTraverse(node, ref inferedType, false, null, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); BinaryExpressionNode binaryNode = node as BinaryExpressionNode; } compileStateTracker.InferedType = inferedType; this.pc = compileStateTracker.startPC; return codeBlock.codeBlockId; }
public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (compileStateTracker.Options.IsDeltaExecution) { if (context != null && context.symbolTable != null) { Validity.Assert(context.symbolTable.symbolList != null && context.symbolTable.symbolList.Count > 0); codeBlock.symbolTable = context.symbolTable; } } AllocateContextGlobals(); compileStateTracker.startPC = this.pc; if (compileStateTracker.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { return EmitExpressionInterpreter(codeBlockNode); } this.localCodeBlockNode = codeBlockNode; ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode; bool isTopBlock = null == codeBlock.parent; if (!isTopBlock) { // If this is an inner block where there can be no classes, we can start at parsing at the global function state compilePass = ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncSig; } codeblock.Body = SplitMulitpleAssignment(codeblock.Body); codeblock.Body = BuildSSA(codeblock.Body, context); if (compileStateTracker.Options.DumpIL) { CodeGenDS codegenDS = new CodeGenDS(codeblock.Body); EmitCompileLog(codegenDS.GenerateCode()); } bool hasReturnStatement = false; ProtoCore.Type inferedType = new ProtoCore.Type(); while (ProtoCore.DSASM.AssociativeCompilePass.kDone != compilePass) { foreach (AssociativeNode node in codeblock.Body) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; // // TODO Jun: Handle stand alone language blocks // Integrate the subPass into a proper pass // // **Need to take care of EmitImportNode, in which I used the same code to handle imported language block nodes - Randy // if (node is LanguageBlockNode) { // Build a binaryn node with a temporary lhs for every stand-alone language block var iNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar()); var langBlockNode = nodeBuilder.BuildBinaryExpression(iNode, node); DfsTraverse(langBlockNode, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); } else { DfsTraverse(node, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); SetDeltaCompilePC(node); } if (NodeUtils.IsReturnExpressionNode(node)) hasReturnStatement = true; } if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && !hasReturnStatement) { EmitReturnNull(); } compilePass++; // We have compiled all classes if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && isTopBlock) { EmitFunctionCallToInitStaticProperty(codeblock.Body); } } ResolveFinalNodeRefs(); if (codeBlock.parent == null) // top-most langauge block { ResolveFunctionGroups(); } compileStateTracker.InferedType = inferedType; if (compileStateTracker.AsmOutput != Console.Out) { compileStateTracker.AsmOutput.Flush(); } this.localCodeBlockNode = codeBlockNode; return codeBlock.codeBlockId; }
public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (core.Options.IsDeltaExecution) { if (context != null && context.symbolTable != null) { Validity.Assert(context.symbolTable.symbolList != null && context.symbolTable.symbolList.Count > 0); codeBlock.symbolTable = context.symbolTable; } } AllocateContextGlobals(); core.startPC = this.pc; if (core.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { return EmitExpressionInterpreter(codeBlockNode); } this.localCodeBlockNode = codeBlockNode; ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode; bool isTopBlock = null == codeBlock.parent; if (!isTopBlock) { // If this is an inner block where there can be no classes, we can start at parsing at the global function state compilePass = ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncSig; } codeblock.Body = SplitMulitpleAssignment(codeblock.Body); bool hasReturnStatement = false; ProtoCore.Type inferedType = new ProtoCore.Type(); bool ssaTransformed = false; while (ProtoCore.DSASM.AssociativeCompilePass.kDone != compilePass) { // Emit SSA only after generating the class definitions if (core.Options.GenerateSSA) { if (compilePass > AssociativeCompilePass.kClassName && !ssaTransformed) { if (!core.IsParsingCodeBlockNode && !core.Options.IsDeltaExecution) { //Audit class table for multiple symbol definition and emit warning. this.core.ClassTable.AuditMultipleDefinition(this.core.BuildStatus, graphNode == null ? default(Guid) : graphNode.guid); } codeblock.Body = BuildSSA(codeblock.Body, context); core.CachedSSANodes.Clear(); core.CachedSSANodes.AddRange(codeblock.Body); ssaTransformed = true; if (core.Options.DumpIL) { CodeGenDS codegenDS = new CodeGenDS(codeblock.Body); EmitCompileLog(codegenDS.GenerateCode()); } } } foreach (AssociativeNode node in codeblock.Body) { inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); // // TODO Jun: Handle stand alone language blocks // Integrate the subPass into a proper pass // // **Need to take care of EmitImportNode, in which I used the same code to handle imported language block nodes - Randy // if (node is LanguageBlockNode) { // Build a binaryn node with a temporary lhs for every stand-alone language block var iNode = nodeBuilder.BuildIdentfier(core.GenerateTempLangageVar()); var langBlockNode = nodeBuilder.BuildBinaryExpression(iNode, node); DfsTraverse(langBlockNode, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); } else { DfsTraverse(node, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); SetDeltaCompilePC(node); } if (NodeUtils.IsReturnExpressionNode(node)) hasReturnStatement = true; } if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && !hasReturnStatement) { EmitReturnNull(); } compilePass++; // We have compiled all classes if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && isTopBlock) { EmitFunctionCallToInitStaticProperty(codeblock.Body); } } ResolveFinalNodeRefs(); ResolveSSADependencies(); if (codeBlock.parent == null) // top-most langauge block { ResolveFunctionGroups(); } core.InferedType = inferedType; if (core.AsmOutput != Console.Out) { core.AsmOutput.Flush(); } this.localCodeBlockNode = codeBlockNode; // Reset the callsite guids in preparation for the next compilation core.CallsiteGuidMap = new Dictionary<Guid, int>(); return codeBlock.codeBlockId; }