internal BBSplitter(Splicer splicer) { this.splicer = splicer; branchTargets = new TrivialHashtable(); blockList = new List<BasicBlock>(); continuationStack = new Stack<BasicBlock>(); scopeStack = new Stack<Scope>(); handlerBlocks = new Stack<BasicBlock>(); }
public Normalizer(Splicer splicer, AttributeList attributes, bool secondOfTwo) { this.splicer = splicer; this.attributes = attributes; this.secondOfTwo = secondOfTwo; }
public override void CompileParseTree(Compilation compilation, ErrorNodeList errorNodes) { TrivialHashtable ambiguousTypes = new TrivialHashtable(); TrivialHashtable scopeFor = new TrivialHashtable(); TrivialHashtable referencedLabels = new TrivialHashtable(); Hashtable exceptionNames = new Hashtable(); ErrorHandler errorHandler = new ErrorHandler(errorNodes); string target = ""; ZingCompilerOptions zoptions = compilation.CompilerParameters as ZingCompilerOptions; if (zoptions != null && zoptions.DumpSource) { target = compilation.CompilerParameters.OutputAssembly; if (string.IsNullOrEmpty(target)) { target = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar; } string output = Path.GetDirectoryName(target); if (string.IsNullOrEmpty(output)) output = Directory.GetCurrentDirectory(); target = Path.GetFileNameWithoutExtension(target); } if (this.Options == null) this.Options = compilation.CompilerParameters; //Attach scopes to namespaces and types so that forward references to base types can be looked up in the appropriate namespace scope Scoper scoper = new Scoper(scopeFor); scoper.VisitCompilation(compilation); //Walk IR looking up names TypeSystem typeSystem = new TypeSystem(errorHandler); Looker looker = new Looker(compilation.GlobalScope, errorHandler, scopeFor, typeSystem, // LJW: added typeSystem ambiguousTypes, referencedLabels, exceptionNames); looker.VisitCompilation(compilation); //Walk IR inferring types and resolving overloads Resolver resolver = new Resolver(errorHandler, typeSystem); resolver.VisitCompilation(compilation); Checker checker = new Checker(errorHandler, typeSystem, scopeFor, ambiguousTypes, referencedLabels); // LJW: added scopeFor checker.VisitCompilation(compilation); // Walk the Zing IR splicing it into our code-gen templates Splicer splicer = new Splicer(this.Options, referencedLabels, exceptionNames); CompilationUnit cuMerged = splicer.CodeGen(compilation); // // If the 'dumpSource' option is given, then we decompile the IR to C# and write this // to a file. // if (zoptions != null && zoptions.DumpSource) { // Once the codegen is done and we have the IR for the generated code, we use the // decompiler to get C# back out, and hand this to the standard compiler. Later, // we'll replace this with the X# normalizer and avoid going in and out of source // code (except for compiler debugging). string tempSrc; string tempName = compilation.CompilerParameters.OutputAssembly + ".cs"; Decompiler decompiler = new Decompiler(); tempSrc = decompiler.Decompile(cuMerged); StreamWriter sw = File.CreateText(tempName); sw.Write(tempSrc); sw.Close(); } if (zoptions != null && zoptions.DumpLabels) { string tempName = compilation.CompilerParameters.OutputAssembly + ".labels"; StreamWriter sw = File.CreateText(tempName); sw.Write(splicer.LabelString); sw.Close(); } for (int i = 0; i < RequiredTypes.Length; i++) { R.Assembly asm = R.Assembly.GetAssembly(RequiredTypes[i]); if (!compilation.CompilerParameters.ReferencedAssemblies.Contains(asm.Location)) compilation.CompilerParameters.ReferencedAssemblies.Add(asm.Location); } // The if-statement added by Jiri Adamek // It loads a native ZOM assembly if used if (zoptions != null && zoptions.ZomAssemblyName != null) { compilation.CompilerParameters.ReferencedAssemblies.Add(zoptions.ZomAssemblyName); } CS.Compiler csCompiler = new CS.Compiler(); // We have to create a new module to pull in references from the // assemblies we just added above. compilation.TargetModule = this.targetModule = csCompiler.CreateModule(compilation.CompilerParameters, errorNodes); // Our one top-level type must be added to the module's type list compilation.TargetModule.Types.Add(((Namespace)cuMerged.Nodes[0]).NestedNamespaces[0].Types[0]); // The restorer patches the DeclaringModule field of our types Restorer restorer = new Restorer(compilation.TargetModule); restorer.VisitCompilationUnit(cuMerged); // Replace the Zing compilation unit with our generated code before invoking // the Spec# back end. compilation.CompilationUnits = new CompilationUnitList(cuMerged); foreach (CompilationUnit cunit in compilation.CompilationUnits) cunit.Compilation = compilation; // For retail builds, disable the time-consuming definite-assignment checks // in the Spec# compiler. if (!this.Options.IncludeDebugInformation) compilation.CompilationUnits[0].PreprocessorDefinedSymbols["NODEFASSIGN"] = "true"; // Let the Spec# back end process the IR from here csCompiler.CompileParseTree(compilation, errorNodes); }
// // This is the primary entry point into BBSplitter. This is called from the // Splicer to do basic block analysis before using the Normalizer to do code-gen // for each basic block. // public static List<BasicBlock> SplitMethod(ZMethod method, Splicer splicer) { BBSplitter splitter = new BBSplitter(splicer); splitter.atomicBranches = new List<BasicBlock>(); splitter.scopeStack.Push(method.Body.Scope); BasicBlock finalBlock = splitter.AddBlock(new BasicBlock(null)); if (method.Atomic) { // // For summarization, we need for atomic methods to have an "extra" // terminating block. This corresponds to what happens in VisitAtomic // for regular atomic blocks. // finalBlock = splitter.AddBlock(new BasicBlock(null, finalBlock)); finalBlock.MiddleOfTransition = true; splitter.insideAtomicBlock = true; } splitter.PushContinuationStack(finalBlock); splitter.VisitStatementList(method.Body.Statements); // For each branch within the atomic block, we need to look at the target // and see if it too is within an atomic block (by definition, the same // one). If not, then we need to make the branch's block be the effective // end of the atomic execution. We can do this by resetting its atomicity // level foreach (BasicBlock b in splitter.atomicBranches) { // The actual branch target is two blocks away because branch targets // always introduce an extra block that flow atomically into "real" code. BasicBlock branchTarget; if (b.UnconditionalTarget.IsReturn) continue; Debug.Assert(b.UnconditionalTarget.UnconditionalTarget != null); branchTarget = b.UnconditionalTarget.UnconditionalTarget; // If the target isn't atomic, then we need to introduce an interleaving // just after the branch. We do this by forcing it to be the end of // the atomic block. We must also make sure such a block cannot be the entry // point of the atomic block. if (branchTarget.RelativeAtomicLevel == 0) { b.RelativeAtomicLevel = 0; b.IsAtomicEntry = false; } } BasicBlock firstBlock = splitter.PopContinuationStack(); firstBlock.IsEntryPoint = true; if (firstBlock.RelativeAtomicLevel > 0) firstBlock.IsAtomicEntry = true; return splitter.blockList; }