예제 #1
0
 public ArmadaSymbolTable(Program i_prog, ArmadaStructs i_structs)
 {
     prog            = i_prog;
     globalVariables = new ArmadaGlobalVariableSymbolTable();
     localVariables  = new ArmadaMethodLocalVariableSymbolTable();
     defaultClass    = null;
     if (i_structs == null)
     {
         structs = new ArmadaStructs(null);
     }
     else
     {
         structs = i_structs;
     }
     threadRoutines = new HashSet <string> {
         "main"
     };
     functionNames         = new List <string> {
     };
     nextRoutines          = new List <NextRoutine>();
     allMethodsInfo        = new AllMethodsInfo(prog);
     tauNextRoutine        = null;
     methodAndLabelToPCMap = new Dictionary <string, ArmadaPC>();
     pcToLabelMap          = new Dictionary <ArmadaPC, string>();
     globalInvariants      = new Dictionary <string, GlobalInvariantInfo>();
     yieldPredicates       = new Dictionary <string, YieldPredicateInfo>();
 }
예제 #2
0
 public void AddClass(ClassDecl c, bool fromStructsModule, ArmadaStructs structs)
 {
     if (c.IsDefaultClass)
     {
         defaultClass = c;
         globalVariables.AddClassInfo(prog, defaultClass, structs);
         foreach (MemberDecl member in defaultClass.Members)
         {
             if (member is Method)
             {
                 var meth = (Method)member;
                 localVariables.AddMethodInfo(prog, defaultClass, this, meth, fromStructsModule, structs);
             }
             else if (member is Function)
             {
                 functionNames.Add(member.Name);
             }
             else if (member is GlobalInvariantDecl)
             {
                 AddGlobalInvariant((GlobalInvariantDecl)member);
             }
             else if (member is YieldPredicateDecl)
             {
                 AddYieldPredicate((YieldPredicateDecl)member);
             }
             else if (member is UniversalStepConstraintDecl)
             {
                 AddUniversalStepConstraint((UniversalStepConstraintDecl)member);
             }
         }
     }
 }
예제 #3
0
 public static bool IsValidType(Type type, ArmadaStructs structs)
 {
     if (type is PointerType pt)
     {
         return(IsValidHeapType(pt.Arg, structs)); // Pointer types are only valid if they point to heap types
     }
     else if (IsPrimitiveType(type))
     {
         return(true);
     }
     else if (type is UserDefinedType ut)
     {
         return(true);
     }
     else if (type is SizedArrayType at)
     {
         return(IsValidType(at.Range, structs));
     }
     else if (type is SeqType seqt)
     {
         return(IsValidType(seqt.Arg, structs));
     }
     else if (type is SetType sett)
     {
         return(IsValidType(sett.Arg, structs));
     }
     else if (type is MultiSetType mst)
     {
         return(IsValidType(mst.Arg, structs));
     }
     else if (type is MapType mt)
     {
         return(IsValidType(mt.Domain, structs) && IsValidType(mt.Range, structs));
     }
     else if (type is ArrowType arrowt)
     {
         return(arrowt.Args.All(subtype => IsValidType(subtype, structs)) && IsValidType(arrowt.Result, structs));
     }
     else if (type == null)
     {
         return(false);
     }
     else
     {
         return(true);
     }
 }
예제 #4
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);
            }
        }
예제 #5
0
 public void AddClassInfo(Program prog, ClassDecl c, ArmadaStructs structs)
 {
     if (!c.IsDefaultClass)
     {
         AH.PrintError(prog, "Internal error:  ArmadaGlobalVariableSymbolTable.AddClassInfo called on non-default class");
         return;
     }
     foreach (MemberDecl member in c.Members)
     {
         if (member is Field)
         {
             var f = (Field)member;
             variableNames.Add(f.Name);
             ArmadaVariable av = null;
             if (!AH.IsValidType(f.Type, structs))
             {
                 AH.PrintError(prog, $"Global variable {f.Name} has invalid type {f.Type}");
                 av = null;
             }
             else if (f.IsGhost)
             {
                 av = new GlobalGhostArmadaVariable(f.Name, f.Type, f.InitialValue);
             }
             else if (f.IsNoAddr)
             {
                 av = new GlobalUnaddressableArmadaVariable(f.Name, f.Type, f.InitialValue);
             }
             else
             {
                 if (AH.IsValidHeapType(f.Type, structs))
                 {
                     av = new GlobalAddressableArmadaVariable(f.Name, f.Type, f.InitialValue);
                 }
                 else
                 {
                     AH.PrintError(prog, $"Global variable {f.Name} has type {f.Type} that can't be used on the heap. Consider making it noaddr or ghost.");
                     av = null;
                 }
             }
             table.Add(f.Name, av);
         }
     }
 }
예제 #6
0
 public static bool IsValidHeapType(Type type, ArmadaStructs structs)
 {
     if (type is PointerType pt)
     {
         return(IsValidHeapType(pt.Arg, structs));
     }
     else if (IsPrimitiveType(type))
     {
         return(true);
     }
     else if (type is UserDefinedType ut)
     {
         return(structs.DoesStructExist(ut.Name)); // Datatypes aren't allowed on the heap, only structs
     }
     else if (type is SizedArrayType at)
     {
         return(IsValidHeapType(at.Range, structs));
     }
     else
     {
         return(false);
     }
 }
예제 #7
0
        private void ExtractLocalVariables(Program prog, Statement stmt, string methodName, ArmadaSingleMethodSymbolTable smst,
                                           ArmadaStructs structs)
        {
            if (stmt is BlockStmt)
            {
                var s = (BlockStmt)stmt;
                foreach (var substmt in s.Body)
                {
                    ExtractLocalVariables(prog, substmt, methodName, smst, structs);
                }
            }
            else if (stmt is IfStmt)
            {
                var s = (IfStmt)stmt;
                ExtractLocalVariables(prog, s.Thn, methodName, smst, structs);
                ExtractLocalVariables(prog, s.Els, methodName, smst, structs);
            }
            else if (stmt is WhileStmt)
            {
                var s = (WhileStmt)stmt;
                ExtractLocalVariables(prog, s.Body, methodName, smst, structs);
            }
            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;
                        }
                    }

                    if (!AH.IsValidType(local.OptionalType, structs))
                    {
                        AH.PrintError(prog, stmt.Tok, $"Local variable {local.Name} in method {methodName} has invalid type {local.OptionalType}");
                        continue;
                    }

                    ArmadaVariable v;
                    if (local.IsNoAddr)
                    {
                        v = new MethodStackFrameUnaddressableLocalArmadaVariable(local.Name, local.OptionalType, initialValue, ArmadaVarType.Local, methodName);
                    }
                    else
                    {
                        if (!AH.IsValidHeapType(local.OptionalType, structs))
                        {
                            AH.PrintError(prog, stmt.Tok, $"Local variable {local.Name} in method {methodName} has type {local.OptionalType} that can't be used on the heap. Consider using noaddr instead.");
                            continue;
                        }
                        v = new MethodStackFrameAddressableLocalArmadaVariable(local.Name, local.OptionalType, initialValue,
                                                                               s.BypassStoreBuffers, methodName);
                    }
                    smst.AddVariable(prog, v);
                }
            }
        }