コード例 #1
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public WhilePCNode(ArmadaPC i_pc, NextRoutine i_nextRoutineWhenTrue, NextRoutine i_nextRoutineWhenFalse, PCNode i_successorWhenTrue,
                    PCNode i_successorWhenFalse) : base(i_pc)
 {
     nextRoutineWhenTrue  = i_nextRoutineWhenTrue;
     nextRoutineWhenFalse = i_nextRoutineWhenFalse;
     successorWhenTrue    = i_successorWhenTrue;
     successorWhenFalse   = i_successorWhenFalse;
 }
コード例 #2
0
ファイル: SymbolTable.cs プロジェクト: b-xiang/Armada
        public bool IsNonyieldingPC(ArmadaPC pc)
        {
            if (pc == null)
            {
                return(false);
            }
            var method = allMethodsInfo.LookupMethod(pc.methodName);

            return(method == null ? false : method.IsNonyieldingPC(pc));
        }
コード例 #3
0
        public string GetStoreBufferEntry(string val_new, ArmadaPC pc)
        {
            var loc = GetStoreBufferLocation();

            if (loc == null)
            {
                return(null);
            }
            return($"Armada_StoreBufferEntry({loc}, {AH.GetPrimitiveValueConstructorName(type)}({val_new}), {pc.ToString()})");
        }
コード例 #4
0
ファイル: SymbolTable.cs プロジェクト: ScriptBox21/MS-Armada
        public string GetNameForPC(ArmadaPC pc)
        {
            string labelStr = GetLabelForPC(pc);

            if (labelStr != null)
            {
                return(labelStr);
            }
            return(pc.instructionCount.ToString());
        }
コード例 #5
0
ファイル: SymbolTable.cs プロジェクト: ScriptBox21/MS-Armada
        public ArmadaPC GenerateOnePC()
        {
            int pcVal = numPCs;

            ++numPCs;
            var pc = new ArmadaPC(symbols, method.Name, pcVal);

            symbols.AssociateLabelWithPC(pcVal.ToString(), pc);
            return(pc);
        }
コード例 #6
0
ファイル: AstDiff.cs プロジェクト: ScriptBox21/MS-Armada
        private bool AdjacentPC(ArmadaPC lhs, ArmadaPC rhs)
        {
            if (lhs.methodName == null || rhs.methodName == null)
            {
                Console.WriteLine("Invalid PC");
                return(false);
            }

            return(lhs.methodName == rhs.methodName && lhs.instructionCount + 1 == rhs.instructionCount);
        }
コード例 #7
0
ファイル: AtomicSpec.cs プロジェクト: b-xiang/Armada
 public AtomicPathPrefix(AtomicSpec i_atomicSpec, ArmadaPC pc)
 {
     atomicSpec   = i_atomicSpec;
     nextRoutines = new List <NextRoutine>();
     tau          = false;
     startPC      = endPC = pc;
     startType    = endType = atomicSpec.GetPCAtomicType(pc);
     extensions   = new List <AtomicPathPrefix>();
     path         = null;
 }
コード例 #8
0
ファイル: SymbolTable.cs プロジェクト: ScriptBox21/MS-Armada
 public EnablingConstraintCollector GetEnablingConstraintCollector(ArmadaPC pc)
 {
     if (constraints.ContainsKey(pc))
     {
         return(constraints[pc]);
     }
     else
     {
         return(null);
     }
 }
コード例 #9
0
ファイル: SymbolTable.cs プロジェクト: ScriptBox21/MS-Armada
 public string GetLabelForPC(ArmadaPC pc)
 {
     if (pcToLabelMap.ContainsKey(pc))
     {
         return(pcToLabelMap[pc]);
     }
     else
     {
         return(null);
     }
 }
コード例 #10
0
ファイル: SymbolTable.cs プロジェクト: ScriptBox21/MS-Armada
        public void AssociateLabelWithPC(string labelStr, ArmadaPC pc)
        {
            var fullLabelStr = pc.methodName + "_" + labelStr;

            if (methodAndLabelToPCMap.ContainsKey(fullLabelStr))
            {
                AH.PrintError(prog, $"ERROR:  More than one label named {labelStr} in method {pc.methodName}");
            }
            methodAndLabelToPCMap[fullLabelStr] = pc;
            pcToLabelMap[pc] = labelStr;
        }
コード例 #11
0
ファイル: SymbolTable.cs プロジェクト: b-xiang/Armada
 public MethodInfo(Program i_prog, ArmadaSymbolTable i_symbols, Method i_method)
 {
     prog                  = i_prog;
     symbols               = i_symbols;
     method                = i_method;
     numPCs                = 0;
     constraints           = new Dictionary <ArmadaPC, EnablingConstraintCollector>();
     returnPC              = null;
     nonyieldingPCs        = new HashSet <ArmadaPC>();
     parsedBody            = null;
     atomicCallsAndReturns = false;
 }
コード例 #12
0
ファイル: AstDiff.cs プロジェクト: ScriptBox21/MS-Armada
        private ArmadaPC GetRoot(ArmadaPC key, Dictionary <ArmadaPC, ArmadaPC> unionFind)
        {
            if (unionFind.ContainsKey(key))
            {
                unionFind[key] = GetRoot(unionFind[key], unionFind);
            }
            else
            {
                return(key);
            }

            return(unionFind[key]);
        }
コード例 #13
0
ファイル: SymbolTable.cs プロジェクト: b-xiang/Armada
        public void AddEnablingConstraint(Program prog, ArmadaPC pc, Expression e)
        {
            if (!constraints.ContainsKey(pc))
            {
                constraints[pc] = new EnablingConstraintCollector(prog);
            }
            var constraintCollector = constraints[pc];
            var context             = new EnablingConstraintResolutionContext(constraintCollector, method.Name, symbols);
            var rvalue = context.ResolveAsRValue(e);

            constraintCollector.AddConjunct(rvalue.UndefinedBehaviorAvoidance);
            constraintCollector.AddConjunct(rvalue.Val);
        }
コード例 #14
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
        private static PCNode GeneratePCStructureForMethodWithNoBody(ArmadaSymbolTable symbols, MethodInfo methodInfo, HashSet <ArmadaPC> loopHeads)
        {
            Method method = methodInfo.method;

            var startPC = new ArmadaPC(symbols, method.Name, 0);
            var midPC   = new ArmadaPC(symbols, method.Name, 1);
            var endPC   = new ArmadaPC(symbols, method.Name, 2);

            PCNode endNode         = new ReturningPCNode(endPC);
            PCNode loopRestartNode = new LoopRestartPCNode(midPC);
            PCNode midNode         = new WhilePCNode(midPC, method.externContinueNextRoutine, method.externEndNextRoutine, loopRestartNode, endNode);
            PCNode startNode       = new NormalPCNode(startPC, method.externStartNextRoutine, midNode);

            loopHeads.Add(midPC);
            return(new StartingPCNode(startPC, startNode));
        }
コード例 #15
0
ファイル: NextRoutine.cs プロジェクト: b-xiang/Armada
 public NextRoutine(Program i_prog, ArmadaSymbolTable i_symbols, NextType i_nextType, MethodInfo i_methodInfo,
                    ArmadaStatement i_armadaStatement, Statement i_stmt, ArmadaPC i_startPC, ArmadaPC i_endPC,
                    List <NextFormal> i_formals, string i_nameSuffix, bool i_undefinedBehavior, bool i_stopping)
 {
     prog              = i_prog;
     symbols           = i_symbols;
     nextType          = i_nextType;
     methodInfo        = i_methodInfo;
     armadaStatement   = i_armadaStatement;
     stmt              = i_stmt;
     startPC           = i_startPC;
     endPC             = i_endPC;
     formals           = new List <NextFormal>(i_formals);
     nameSuffix        = i_nameSuffix;
     undefinedBehavior = i_undefinedBehavior;
     stopping          = i_stopping;
 }
コード例 #16
0
ファイル: NextRoutine.cs プロジェクト: b-xiang/Armada
        public NextRoutineConstructor(Program i_prog, ArmadaSymbolTable i_symbols, NextType i_nextType, MethodInfo i_methodInfo,
                                      ArmadaStatement i_armadaStatement, Statement i_stmt, ArmadaPC i_startPC, ArmadaPC i_endPC)
        {
            prog     = i_prog;
            symbols  = i_symbols;
            nextType = i_nextType;
            validDefinedStepBuilder   = new PredicateBuilder(i_prog, true);
            validUndefinedStepBuilder = new PredicateBuilder(i_prog, false);
            getNextStateBuilder       = new ExpressionBuilder(i_prog);
            methodInfo      = i_methodInfo;
            method          = methodInfo == null ? null : methodInfo.method;
            armadaStatement = i_armadaStatement;
            stmt            = i_stmt;
            startPC         = i_startPC;
            endPC           = i_endPC;
            formals         = new List <NextFormal>();
            valid           = true;
            hasUndefinedBehaviorAvoidanceConstraint = false;
            definedBehaviorNextRoutine   = null;
            undefinedBehaviorNextRoutine = null;

            s     = ReserveVariableName("s");
            entry = ReserveVariableName("entry");
            tid   = ReserveVariableName("tid");
            t     = ReserveVariableName("t");
            locv  = ReserveVariableName("locv");

            if (startPC != null)
            {
                AddConjunct($"{t}.pc.{startPC}?");
                AddConjunct($"{t}.top.Armada_StackFrame_{startPC.methodName}?");

                if (methodInfo != null)
                {
                    var constraints = methodInfo.GetEnablingConstraintCollector(startPC);
                    if (constraints != null && !constraints.Empty)
                    {
                        AddConjunct($"Armada_EnablingConditions_{startPC}(s, tid)");
                    }
                }

                AddConjunct("Armada_UniversalStepConstraint(s, tid)");
            }
        }
コード例 #17
0
ファイル: AtomicSpec.cs プロジェクト: b-xiang/Armada
        ///////////////////////////////////////////////////////////////////////
        // PC TYPES
        ///////////////////////////////////////////////////////////////////////

        public PCAtomicType GetPCAtomicType(ArmadaPC pc)
        {
            if (pc == null)
            {
                return(PCAtomicType.Yielding);
            }
            if (recurrentPCs.Contains(pc))
            {
                return(PCAtomicType.Recurrent);
            }
            if (nonyieldingPCs.Contains(pc))
            {
                return(PCAtomicType.Nonyielding);
            }
            else
            {
                return(PCAtomicType.Yielding);
            }
        }
コード例 #18
0
ファイル: SymbolTable.cs プロジェクト: b-xiang/Armada
        public void ParseMethodBody(ArmadaSymbolTable symbols)
        {
            var parse = new ParseInfo(prog, symbols, this);

            parsedBody = ArmadaStatement.ParseStatement(parse, method.Body);
            var startPC = GenerateOnePC();

            returnPC = parsedBody.AssignPCs(startPC);

            ArmadaStatement.ComputeNonyieldingPCs(parsedBody, nonyieldingPCs);

            symbols.AssociateLabelWithPC("Start", startPC);
            symbols.AssociateLabelWithPC("End", returnPC);
            foreach (var statement in parsedBody)
            {
                statement.AssociateLabelsWithPCs();
                statement.GenerateEnablingConstraints();
            }
        }
コード例 #19
0
ファイル: AtomicSpec.cs プロジェクト: b-xiang/Armada
        ///////////////////////////////////////////////////////////////////////
        // FINDING RECURRENT PCS
        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// In CheckForFiniteNonyieldingPathBetween, we only care about
        /// paths that reach end before visiting any other node twice
        /// (since if it visits another node twice, it's potentially
        /// infinite).  So, we keep track of nodes we've already visited
        /// and don't visit them again.
        /// </summary>

        private bool CheckForFiniteNonyieldingPathBetween(ArmadaPC start, ArmadaPC end, HashSet <ArmadaPC> alreadyVisited)
        {
            if (start == null || end == null)
            {
                return(false);
            }
            if (!nonyieldingPCs.Contains(start))
            {
                return(false);
            }
            List <NextRoutine> nextRoutines;

            if (!pcToNextRoutines.TryGetValue(start, out nextRoutines))
            {
                return(false);
            }
            foreach (var nextRoutine in nextRoutines)
            {
                var nextPC = nextRoutine.endPC;
                if (nextPC.Equals(end))
                {
                    return(true);
                }
                if (alreadyVisited.Contains(nextPC))
                {
                    continue;
                }
                alreadyVisited.Add(nextPC);
                if (CheckForFiniteNonyieldingPathBetween(nextPC, end, alreadyVisited))
                {
                    return(true);
                }
                alreadyVisited.Remove(nextPC);
            }
            return(false);
        }
コード例 #20
0
        public string UpdateTotalStateWithStoreBufferEntry(ResolutionContext context, IConstraintCollector constraintCollector,
                                                           string val_new, ArmadaPC pc)
        {
            if (NoTSO())
            {
                return(UpdateTotalStateLocationDirectly(context, constraintCollector, val_new));
            }

            if (!AH.IsPrimitiveType(type))
            {
                context.Fail(tok, "Can't do TSO write to non-primitive type; try using ::= instead of :=");
                return(null);
            }

            var entry = GetStoreBufferEntry(val_new, pc);

            if (entry == null)
            {
                context.Fail(tok, "Can't do a TSO write to that location; try using ::= instead of :=");
                return(null);
            }

            return($"Armada_AppendToThreadStoreBuffer({context.GetLValueState()}, {context.tid}, {entry})");
        }
コード例 #21
0
ファイル: AtomicSpec.cs プロジェクト: b-xiang/Armada
        private bool DoesNonyieldingPathBetweenPCsExist(ArmadaPC start, ArmadaPC end)
        {
            var alreadyVisited = new HashSet <ArmadaPC>();

            return(CheckForFiniteNonyieldingPathBetween(start, end, alreadyVisited));
        }
コード例 #22
0
ファイル: AtomicSpec.cs プロジェクト: b-xiang/Armada
        public AtomicPathPrefix(AtomicSpec i_atomicSpec, List <NextRoutine> i_nextRoutines, bool i_tau, AtomicPathPrefix parent)
        {
            atomicSpec   = i_atomicSpec;
            nextRoutines = new List <NextRoutine>(i_nextRoutines);
            tau          = i_tau;
            startPC      = nextRoutines[0].startPC;
            endPC        = nextRoutines[nextRoutines.Count - 1].endPC;
            startType    = atomicSpec.GetPCAtomicType(startPC);
            endType      = nextRoutines[nextRoutines.Count - 1].Stopping ? PCAtomicType.Stopping : atomicSpec.GetPCAtomicType(endPC);
            extensions   = new List <AtomicPathPrefix>();
            path         = null;

            if (parent != null)
            {
                parent.AddExtension(this);
            }

            if (tau)
            {
                name = "Tau";
            }
            else
            {
                name  = UndefinedBehavior ? "UB_" : "";
                name += $"From_{startPC.methodName}_{startPC.Name}";

                // It's possible for two atomic paths to have the same start
                // and end PCs.  But, every path has to have a distinct name,
                // so we sometimes have to name a path with more than just the
                // start and end PCs.
                //
                // One way for two atomic paths with the same start and end
                // PCs to differ is via returning to different PCs.  For
                // instance, consider the following code:
                //
                //   method {:atomic} A {
                //     S1;
                //   label L:
                //     S2;
                //   }
                //
                //   method B {
                //     atomic {
                //       A();
                //       A();
                //       A();
                //     }
                //   }
                //
                // Here, there are two ways to get from label L to label L:
                // (1) by returning from B's first call to A and then making
                // B's second call to A, and (2) by returning from B's second
                // call to A and then making B's third call to A.  So, to make
                // sure such paths have different names, we include in the
                // name every returned-to PC in a step other than the last one
                // in the path.
                //
                // Another way for two atomic paths with the same start and
                // end PCs to differ is via branch outcomes.  For instance,
                // consider the following code:
                //
                //   atomic {
                //     if P {
                //       S1;
                //     }
                //     S2;
                //   }
                //
                // Here, there are two ways to get from the beginning to the
                // end: via the true branch of the if (passing through
                // statement S1) or via the false branch.  So we distinguish
                // the names of such paths by the branch outcomes.

                bool justBranched = false;
                for (var i = 0; i < nextRoutines.Count; ++i)
                {
                    var nextRoutine = nextRoutines[i];
                    if (i < nextRoutines.Count - 1 && nextRoutine.nextType == NextType.Return)
                    {
                        var returnToPC = nextRoutine.endPC;
                        name        += $"_Via_{returnToPC.methodName}_{returnToPC.Name}";
                        justBranched = false;
                    }

                    bool branchOutcome;
                    if (nextRoutine.TryGetBranchOutcome(out branchOutcome))
                    {
                        if (!justBranched)
                        {
                            name += "_";
                        }
                        name        += (branchOutcome ? "T" : "F");
                        justBranched = true;
                    }
                }

                if (endPC == null)
                {
                    name += "_to_exit";
                }
                else
                {
                    name += $"_To_{endPC.methodName}_{endPC.Name}";
                }
            }
        }
コード例 #23
0
ファイル: AtomicSpec.cs プロジェクト: b-xiang/Armada
 public IEnumerable <AtomicPathPrefix> RootPathPrefixesByPC(ArmadaPC pc)
 {
     return(rootPathPrefixesByPC[pc]);
 }
コード例 #24
0
ファイル: Combining.cs プロジェクト: b-xiang/Armada
        ////////////////////////////////////////////////////////////////////////
        /// PC map
        ////////////////////////////////////////////////////////////////////////

        bool MakePCMap()
        {
            startPC = pgp.symbolsLow.GetPCForMethodAndLabel(strategy.StartLabel.val);
            if (startPC == null)
            {
                AH.PrintError(pgp.prog, $"You specified a start label for combining of {strategy.StartLabel.val}, but that label doesn't exist in level {pgp.mLow.Name}.  Remember to prefix label names with the method name and an underscore, e.g., use main_lb1 if you have label lb1: in method main.");
                return(false);
            }

            endPC = pgp.symbolsLow.GetPCForMethodAndLabel(strategy.EndLabel.val);
            if (endPC == null)
            {
                AH.PrintError(pgp.prog, $"You specified an end label for combining of {strategy.EndLabel.val}, but that label doesn't exist in level {pgp.mLow.Name}.  Remember to prefix label names with the method name and an underscore, e.g., use main_lb1 if you have label lb1: in method main.");
                return(false);
            }

            if (endPC.methodName != startPC.methodName)
            {
                AH.PrintError(pgp.prog, $"The start and end labels you provided for combining aren't from the same method in {pgp.mLow.Name}.  The start label {strategy.StartLabel.val} is in method {startPC.methodName} and the end label {strategy.EndLabel.val} is in method {endPC.methodName}.");
                return(false);
            }

            if (endPC.instructionCount <= startPC.instructionCount)
            {
                AH.PrintError(pgp.prog, $"The end label you provided for combining ({strategy.EndLabel.val}) isn't after the start label you provided for combining ({strategy.StartLabel.val}).");
                return(false);
            }

            singlePC = pgp.symbolsHigh.GetPCForMethodAndLabel(strategy.SingleLabel.val);
            if (singlePC == null)
            {
                AH.PrintError(pgp.prog, $"You specified a single label for combining of {strategy.SingleLabel.val}, but that label doesn't exist in level {pgp.mHigh.Name}.  Remember to prefix label names with the method name and an underscore, e.g., use main_lb1 if you have label lb1: in method main.");
                return(false);
            }

            if (singlePC.methodName != startPC.methodName)
            {
                AH.PrintError(pgp.prog, $"The start and end labels you provided for combining aren't from the same method as the single label you provided.  That is, {strategy.StartLabel.val} and {strategy.EndLabel.val} are both from method {startPC.methodName}, but the single label {strategy.SingleLabel.val} is from method {singlePC.methodName}.");
                return(false);
            }

            if (singlePC.instructionCount != startPC.instructionCount)
            {
                AH.PrintError(pgp.prog, $"The start label you provided isn't at the same position in its method as the single label you provided.  That is, {strategy.StartLabel.val} is preceded by {startPC.instructionCount} instructions in {pgp.mLow.Name}, but {strategy.SingleLabel.val} is preceded by {singlePC.instructionCount} instructions in {pgp.mHigh.Name}.");
                return(false);
            }

            pcMap = new Dictionary <ArmadaPC, ArmadaPC>();
            var pcs = new List <ArmadaPC>();

            pgp.symbolsLow.AllMethods.AppendAllPCs(pcs);
            foreach (var pc in pcs)
            {
                if (pc.methodName != startPC.methodName)
                {
                    pcMap[pc] = pc.CloneWithNewSymbolTable(pgp.symbolsHigh);
                }
                else if (pc.instructionCount < startPC.instructionCount)
                {
                    pcMap[pc] = pc.CloneWithNewSymbolTable(pgp.symbolsHigh);
                }
                else if (pc.instructionCount == startPC.instructionCount)
                {
                    pcMap[pc] = singlePC;
                }
                else if (pc.instructionCount <= endPC.instructionCount)
                {
                    pcMap[pc] = new ArmadaPC(pgp.symbolsHigh, pc.methodName, singlePC.instructionCount + 1);
                }
                else
                {
                    pcMap[pc] = new ArmadaPC(pgp.symbolsHigh, pc.methodName, pc.instructionCount + startPC.instructionCount - endPC.instructionCount);
                }
            }

            ExtendPCMapWithExternalAndStructsMethods();
            GenerateNextRoutineMap(false);

            return(true);
        }
コード例 #25
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public NormalPCInfo(ArmadaPC pc) : base(pc)
 {
 }
コード例 #26
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public ForkSitePCInfo(ArmadaPC pc) : base(pc)
 {
 }
コード例 #27
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public CallSitePCInfo(ArmadaPC pc) : base(pc)
 {
 }
コード例 #28
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public ReturnSitePCInfo(ArmadaPC pc) : base(pc)
 {
 }
コード例 #29
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public ReturningPCNode(ArmadaPC i_pc) : base(i_pc)
 {
 }
コード例 #30
0
ファイル: PCGraph.cs プロジェクト: ScriptBox21/MS-Armada
 public LoopRestartPCNode(ArmadaPC i_pc) : base(i_pc)
 {
 }