Esempio n. 1
0
        public void AddMethodInfo(Program prog, ClassDecl c, ArmadaSymbolTable symbols, Method meth, bool fromStructsModule,
                                  ArmadaStructs structs)
        {
            bool isExternal = (meth.Body is null || Attributes.Contains(meth.Attributes, "extern"));

            var smst = new ArmadaSingleMethodSymbolTable(meth, isExternal, fromStructsModule);

            foreach (var formal in meth.Ins)
            {
                var v = new MethodStackFrameUnaddressableLocalArmadaVariable(formal.Name, formal.Type, null, ArmadaVarType.Input, meth.Name);
                smst.AddVariable(prog, v);
            }

            foreach (var formal in meth.Outs)
            {
                var v = new MethodStackFrameUnaddressableLocalArmadaVariable(formal.Name, formal.Type, null, ArmadaVarType.Output, meth.Name);
                smst.AddVariable(prog, v);
            }

            ExtractLocalVariables(prog, meth.Body, meth.Name, smst, structs);

            if (isExternal && meth.Reads.Expressions != null)
            {
                var reads = meth.Reads.Expressions;
                for (int i = 0; i < reads.Count; ++i)
                {
                    Expression read_expr = reads.ElementAt(i);
                    var        varName   = $"Armada_Extern{i}";
                    var        v         = new MethodStackFrameUnaddressableLocalArmadaVariable(varName, read_expr.Type, null, ArmadaVarType.ExternRead, meth.Name);
                    smst.AddVariable(prog, v);
                }
            }

            if (methodTable.ContainsKey(meth.Name))
            {
                AH.PrintError(prog, $"Method {meth.Name} already defined");
            }
            else
            {
                methodTable[meth.Name] = smst;
            }

            if (isExternal && meth.Body == null)
            {
                ExtractOldVariablesForBodylessMethod(prog, symbols, meth, smst);
            }
        }
Esempio n. 2
0
        protected override bool CheckVariableNameListEquivalence(IEnumerable <string> varNames_l, IEnumerable <string> varNames_h,
                                                                 ArmadaSingleMethodSymbolTable s_l, ArmadaSingleMethodSymbolTable s_h,
                                                                 string methodName, string descriptor)
        {
            var vars_l = varNames_l.ToArray();

            string[] vars_h;
            if (methodName == strategy.MethodName)
            {
                vars_h = varNames_h.Where(v => v != strategy.VariableName).ToArray();
            }
            else
            {
                vars_h = varNames_h.ToArray();
            }

            if (vars_l.Length != vars_h.Length)
            {
                AH.PrintError(pgp.prog, $"Method {methodName} has {vars_l.Length} {descriptor} variables in level {pgp.mLow.Name} but {vars_h.Length} of them in level {pgp.mHigh.Name}");
                return(false);
            }

            for (int i = 0; i < vars_l.Length; ++i)
            {
                var name_l = vars_l[i];
                var name_h = vars_h[i];
                if (name_l != name_h)
                {
                    AH.PrintError(pgp.prog, $"In method {methodName}, {descriptor} non-introduced variable number {i+1} is named {name_l} in level {pgp.mLow.Name} but named {name_h} in level {pgp.mHigh.Name}");
                    return(false);
                }
                var v_l = s_l.LookupVariable(name_l);
                var v_h = s_h.LookupVariable(name_h);
                if (!AH.TypesMatch(v_l.ty, v_h.ty))
                {
                    AH.PrintError(pgp.prog, $"In method {methodName}, the {descriptor} variable named {name_l} has type {v_l.ty} in level {pgp.mLow.Name} but type {v_h.ty} in level {pgp.mHigh.Name}");
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 3
0
        private void ExtractOldVariablesForBodylessMethod(Program prog, ArmadaSymbolTable symbols, Method meth, ArmadaSingleMethodSymbolTable smst)
        {
            if (meth.Ens == null)
            {
                return;
            }
            if (!meth.Ens.Any())
            {
                return;
            }

            var s   = AH.MakeNameSegment("s", "Armada_TotalState");
            var tid = AH.MakeNameSegment("tid", "Armada_ThreadHandle");
            var failureCollector = new SimpleFailureReporter(prog);
            var ensContext       = new BodylessMethodSnapshotResolutionContext(s, tid, meth.Name, symbols, failureCollector);

            foreach (var ens in meth.Ens)
            {
                var ensResolvedJustToGetOldValues = ensContext.ResolveAsRValue(ens.E);
            }
            int whichOldValue = 0;

            foreach (var oldValue in ensContext.OldValues)
            {
                var varName = $"Armada_Old{whichOldValue}";
                var v       = new MethodStackFrameUnaddressableLocalArmadaVariable(varName, oldValue.Type, oldValue, ArmadaVarType.ExternOld, meth.Name);
                ++whichOldValue;
                smst.AddVariable(prog, v);
            }
        }
Esempio n. 4
0
        private void ExtractLocalVariables(Program prog, Statement stmt, string methodName, ArmadaSingleMethodSymbolTable smst)
        {
            if (stmt is BlockStmt)
            {
                var s = (BlockStmt)stmt;
                foreach (var substmt in s.Body)
                {
                    ExtractLocalVariables(prog, substmt, methodName, smst);
                }
            }
            else if (stmt is IfStmt)
            {
                var s = (IfStmt)stmt;
                ExtractLocalVariables(prog, s.Thn, methodName, smst);
                ExtractLocalVariables(prog, s.Els, methodName, smst);
            }
            else if (stmt is WhileStmt)
            {
                var s = (WhileStmt)stmt;
                ExtractLocalVariables(prog, s.Body, methodName, smst);
            }
            else if (stmt is VarDeclStmt)
            {
                var        s      = (VarDeclStmt)stmt;
                UpdateStmt update = null;

                if (s.Update != null)
                {
                    if (!(s.Update is UpdateStmt))
                    {
                        AH.PrintError(prog, stmt.Tok, "Armada only supports *concrete* assignment of local variables during assignment.");
                        return;
                    }
                    else
                    {
                        update = (UpdateStmt)s.Update;
                        if (s.Locals.Count != update.Rhss.Count)
                        {
                            AH.PrintError(prog, s.Tok, $"Number of left-hand sides for assignment ({s.Locals.Count}) statement doesn't match number of right-hand sides ({update.Rhss.Count}).");
                            return;
                        }
                    }
                }

                for (int i = 0; i < s.Locals.Count; ++i)
                {
                    var local = s.Locals[i];
                    if (local.OptionalType is InferredTypeProxy)
                    {
                        AH.PrintError(prog, local.EndTok, "Local variables in Armada layer methods must be given explicit types.");
                        continue;
                    }

                    Expression initialValue = null;
                    if (update != null)
                    {
                        var rhs = update.Rhss[i];
                        if (rhs is HavocRhs)
                        {
                            // No need to do anything special here because in the absence of an initializer we already havoc
                        }
                        else if (rhs is ExprRhs)
                        {
                            var erhs = (ExprRhs)rhs;
                            initialValue = erhs.Expr;
                        }
                        else if (rhs is CreateThreadRhs)
                        {
                            AH.PrintError(prog, rhs.Tok, "Create-thread can't be done in a variable-declaration statement");
                            continue;
                        }
                        else if (rhs is MallocRhs || rhs is CallocRhs)
                        {
                            AH.PrintError(prog, rhs.Tok, "Allocation can't be done in a variable-declaration statement");
                            continue;
                        }
                        else
                        {
                            AH.PrintError(prog, rhs.Tok, "Right-hand side of variable-declaration isn't a valid rvalue");
                            continue;
                        }
                    }

                    ArmadaVariable v;
                    if (local.IsNoAddr)
                    {
                        v = new MethodStackFrameUnaddressableLocalArmadaVariable(local.Name, local.OptionalType, initialValue, ArmadaVarType.Local, methodName);
                    }
                    else
                    {
                        v = new MethodStackFrameAddressableLocalArmadaVariable(local.Name, local.OptionalType, initialValue,
                                                                               s.BypassStoreBuffers, methodName);
                    }
                    smst.AddVariable(prog, v);
                }
            }
        }