// This constructor is only called for Preloading of assemblies and // precompilation of CodeBlockNode nodes in GraphUI for global language blocks - pratapa public CodeGen(Core coreObj) : base(coreObj) { Validity.Assert(core.IsParsingPreloadedAssembly || core.IsParsingCodeBlockNode); classOffset = 0; // either of these should set the console to flood // ignoreRankCheck = false; emitReplicationGuide = false; astNodes = new List<AssociativeNode>(); setConstructorStartPC = false; // Re-use the existing procedureTable and symbolTable to access the built-in and predefined functions ProcedureTable procTable = core.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.Compiler.Associative.CompilePass.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(core); unPopulatedClasses = new Dictionary<int, ClassDeclNode>(); expressionSSATempSymbolList = new Stack<SymbolNode>(); }
private int EmitExpressionInterpreter(ProtoCore.AST.Node codeBlockNode) { core.startPC = this.pc; compilePass = ProtoCore.Compiler.Associative.CompilePass.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 (core.DebugProps.DebugStackFrameContains(DebugProperties.StackFrameFlagOptions.FepRun)) { // Save the current scope for the expression interpreter globalClassIndex = core.watchClassScope = core.Rmem.CurrentStackFrame.ClassScope; globalProcIndex = core.watchFunctionScope = core.Rmem.CurrentStackFrame.FunctionScope; int functionBlock = core.Rmem.CurrentStackFrame.FunctionBlock; if (globalClassIndex != -1) localProcedure = core.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex]; else { // TODO: to investigate whethter to use the table under executable or in core.FuncTable - Randy, Jun localProcedure = core.DSExecutable.procedureTable[functionBlock].procList[globalProcIndex]; } } foreach (AssociativeNode node in codeblock.Body) { inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); DfsTraverse(node, ref inferedType, false, null, ProtoCore.Compiler.Associative.SubCompilePass.kUnboundIdentifier); BinaryExpressionNode binaryNode = node as BinaryExpressionNode; } core.InferedType = inferedType; this.pc = core.startPC; 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.Compiler.Associative.CompilePass.kGlobalFuncSig; } codeblock.Body = SplitMulitpleAssignment(codeblock.Body); bool hasReturnStatement = false; ProtoCore.Type inferedType = new ProtoCore.Type(); bool ssaTransformed = false; while (ProtoCore.Compiler.Associative.CompilePass.kDone != compilePass) { // Emit SSA only after generating the class definitions if (core.Options.GenerateSSA) { if (compilePass > ProtoCore.Compiler.Associative.CompilePass.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); } 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.Compiler.Associative.SubCompilePass.kUnboundIdentifier); } else { DfsTraverse(node, ref inferedType, false, graphNode, ProtoCore.Compiler.Associative.SubCompilePass.kUnboundIdentifier); SetDeltaCompilePC(node); } if (NodeUtils.IsReturnExpressionNode(node)) hasReturnStatement = true; } if (compilePass == ProtoCore.Compiler.Associative.CompilePass.kGlobalScope && !hasReturnStatement) { EmitReturnNull(); } compilePass++; // We have compiled all classes if (compilePass == ProtoCore.Compiler.Associative.CompilePass.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; }
public CodeGen(Core coreObj, ProtoCore.CompileTime.Context callContext, ProtoCore.DSASM.CodeBlock parentBlock = null) : base(coreObj, parentBlock) { context = callContext; classOffset = 0; // either of these should set the console to flood // ignoreRankCheck = false; emitReplicationGuide = false; astNodes = new List<AssociativeNode>(); setConstructorStartPC = false; // Comment Jun: Get the codeblock to use for this codegenerator if (core.Options.IsDeltaExecution) { codeBlock = GetDeltaCompileCodeBlock(parentBlock); if (core.Options.IsDeltaCompile) { pc = codeBlock.instrStream.instrList.Count; } else { pc = core.deltaCompileStartPC; } } else { codeBlock = BuildNewCodeBlock(); } if (null == parentBlock) { if (!core.Options.IsDeltaExecution) { // This is a top level block core.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; } compilePass = ProtoCore.Compiler.Associative.CompilePass.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(core); 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; } */ expressionSSATempSymbolList = new Stack<SymbolNode>(); }