Example #1
0
 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>();
 }
Example #2
0
 public Normalizer(Splicer splicer, AttributeList attributes, bool secondOfTwo)
 {
     this.splicer = splicer;
     this.attributes = attributes;
     this.secondOfTwo = secondOfTwo;
 }
Example #3
0
        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);
        }
Example #4
0
        //
        // 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;
        }