Esempio n. 1
0
		public static Delegate CreateSdfDelegate(SdfInfo sdfInfo, DependencyGraph dpGraph, IList<FullCellAddr> cellList) {
			Debug.Assert(sdfInfo.inputCells == dpGraph.inputCells);
			Debug.Assert(sdfInfo.outputCell == dpGraph.outputCell);
			ProgramLines program = new ProgramLines(sdfInfo.outputCell, sdfInfo.inputCells);
			program.AddComputeCells(dpGraph, cellList);
			// TODO: This is not the final program, so order may not respect eval cond dependencies!
			sdfInfo.Program = program; // Save ComputeCell list for later partial evaluation
			return program.CompileToDelegate(sdfInfo);
		}
Esempio n. 2
0
		/// CodeGenerate.Initialize(ilg) must be called first.
		public void EvalCondReorderCompile() {
			ComputeEvalConds();
			// Re-sort the expressions to reflect new dependencies 
			// introduced by evaluation conditions
			DependencyGraph augmentedGraph
				= new DependencyGraph(outputCell, inputCells, GetComputeCell);
			IList<FullCellAddr> augmentedList = augmentedGraph.PrecedentOrder();
			ProgramLines finalProgram = new ProgramLines(outputCell, inputCells);
			foreach (FullCellAddr cellAddr in augmentedList) {
				finalProgram.AddComputeCell(cellAddr, GetComputeCell(cellAddr));
			}
			// This relies on all pathconds having been generated at this point:
			EmitCacheInitializations();
			finalProgram.CreateUnwrappedNumberCells();
			finalProgram.Compile();
		}
Esempio n. 3
0
		/// <summary>
		/// Compiles the topologically sorted list of Expr to a list (program) 
		/// of ComputeCells, encapsulating CGExprs.  Builds a map from cellAddr to 
		/// local variable ids, for compiling sheet-internal cellrefs to ldloc instructions.  
		/// </summary>
		public void AddComputeCells(DependencyGraph dpGraph, IList<FullCellAddr> cellList) {
			Debug.Assert(dpGraph.outputCell == cellList[cellList.Count - 1]);
			CGExpr outputExpr;
			if (cellList.Count == 0 || cellList.Count == 1 && dpGraph.inputCellSet.Contains(cellList.Single())) {
				// The output cell is also an input cell; load it:
				outputExpr = new CGCellRef(dpGraph.outputCell, addressToVariable[dpGraph.outputCell]);
			}
			else {
				// First process all non-output cells, and ignore all input cells:
				foreach (FullCellAddr cellAddr in cellList) {
					if (cellAddr.Equals(dpGraph.outputCell)) {
						continue;
					}
					HashSet<FullCellAddr> dependents = dpGraph.GetDependents(cellAddr);
					int minUses = dependents.Count;
					if (minUses == 1) {
						FullCellAddr fromFca = dependents.First();
						minUses = Math.Max(minUses, GetCount(fromFca, cellAddr));
					}
					// Now if minUses==1 then there is at most one use of the cell at cellAddr,
					// and no local variable is needed.  Otherwise, allocate a local variable:
					if (minUses > 1) {
						CGExpr newExpr = CGExpressionBuilder.BuildExpression(cellAddr, addressToVariable);
						Variable var = new LocalVariable(cellAddr.ToString(), newExpr.Type());
						AddComputeCell(cellAddr, new ComputeCell(newExpr, var, cellAddr));
					}
				}
				// Then process the output cell:
				outputExpr = CGExpressionBuilder.BuildExpression(dpGraph.outputCell, addressToVariable);
			}
			// Add the output cell expression last, without a variable to bind it to; hence the null,
			// also indicating that (only) the output cell is in tail position:
			AddComputeCell(dpGraph.outputCell, new ComputeCell(outputExpr, null, dpGraph.outputCell));
		}
Esempio n. 4
0
		private ProgramLines PruneZeroUseCells() {
			// This is slightly more general than necessary, since we know that the 
			// new order of FullCellAddrs could be embedded in the old one.  So it would suffice
			// to simply count the number of uses of each FullCellAddr rather than do this sort.
			DependencyGraph dpGraph = new DependencyGraph(outputCell, inputCells, GetComputeCell);
			IList<FullCellAddr> prunedList = dpGraph.PrecedentOrder();
			ProgramLines prunedProgram = new ProgramLines(outputCell, inputCells);
			foreach (FullCellAddr cellAddr in prunedList) {
				prunedProgram.AddComputeCell(cellAddr, GetComputeCell(cellAddr));
			}
			return prunedProgram;
		}
Esempio n. 5
0
 /// <summary>
 /// Compiles entry code and body of a sheet-defined function
 /// </summary>
 /// <param name="info">The SdfInfo object describing the function</param>
 /// <returns></returns>
 private static Delegate CompileSdf(SdfInfo info) {
   // Build dependency graph containing all cells needed by the output cell
   DependencyGraph dpGraph = new DependencyGraph(info.outputCell, info.inputCells,
     delegate(FullCellAddr fca) { return fca.sheet[fca.ca]; });
   // Topologically sort the graph in calculation order; leave out constants
   IList<FullCellAddr> cellList = dpGraph.PrecedentOrder();
   info.SetVolatility(cellList);
   // Convert each Expr into a CGExpr while preserving order.  Inline single-use expressions
   cellToFunctionMapper.AddFunction(info, dpGraph.GetAllNodes());
   return ProgramLines.CreateSdfDelegate(info, dpGraph, cellList);  
 }