Ejemplo n.º 1
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);
         }
     }
 }
Ejemplo n.º 2
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);
                }
            }
        }