private void ParseProcedureDecl(SymTable symTable)
        {
            var      c            = Current;
            SymTable procSymTable = new SymTable {
                Parent = symTable
            };
            var h = ParseProcedureHeading(procSymTable);

            Require(Semicolon);
            if (symTable.Contains(h.Name))
            {
                throw new ParserException($"Duplicate identifier {h.Name}", c.Line, c.Position);
            }
            var p = new ProcedureSymbol {
                Name = h.Name, Parameters = h.Parameters
            };

            symTable.Add(h.Name, p);
            var backup = CurrentReturnType;

            CurrentReturnType = null;
            var b = ParseBlock(procSymTable);

            CurrentReturnType = backup;
            p.Block           = b;
            Require(Semicolon);
        }
        private void Visit(ProcedureNode node)
        {
            var procName = node.Data.Value.ToString();

            var procParams = new List <VariableSymbol>();

            foreach (var parameter in node.Parameters)
            {
                var paramType = CurrentScope.Lookup(parameter.Type.Data.Type.ToString());
                var paramName = parameter.Variable.Data.Value.ToString();
                var varSymbol = new VariableSymbol(paramName, paramType);
                CurrentScope.Insert(varSymbol);
                procParams.Add(varSymbol);
            }

            var procSymbol = new ProcedureSymbol(procName, procParams);

            CurrentScope.Insert(procSymbol);

            var procScope = new SymbolTable(procName, 2, CurrentScope);

            CurrentScope = procScope;

            Visit(node.BlockNode);

            CurrentScope = CurrentScope.ParentScope;
        }
Beispiel #3
0
        public void visit_Call(AST node)
        {
            this.visitAll(node);
            node.type = node.nodes[0].type;
            //Check that call argument types match function parameter types
            Symbol        procOrFunc = this.stm.currentTable.lookup(node.nodes[0].token.lexeme);
            List <Symbol> parameters = null;

            if (procOrFunc != null)
            {
                if (procOrFunc.category == Category.FUNCTION)
                {
                    FunctionSymbol func = (FunctionSymbol)procOrFunc;
                    parameters = func.parameters;
                }
                else
                {
                    ProcedureSymbol proc = (ProcedureSymbol)procOrFunc;
                    parameters = proc.parameters;
                }
            }
            AST arguments = null;

            if (node.nodes.Count == 2)
            {
                arguments = node.nodes[1];
            }
            if (parameters != null && arguments != null)
            {
                if (parameters.Count != arguments.nodes.Count)
                {
                    //count mismatch
                    return;
                }
                for (int i = 0; i < parameters.Count; i++)
                {
                    if (parameters[i].type != arguments.nodes[i].type)
                    {
                        //type mismatch
                    }
                }
            }
            else if (parameters == null && arguments != null)
            {
                //count mismatch
            }
            else if (parameters != null && arguments == null)
            {
                //count mismatch
            }
        }
Beispiel #4
0
        /// <summary>
        /// Reads symbol record from symbol references for the specified index.
        /// </summary>
        /// <param name="index">Index of the symbol record.</param>
        private SymbolRecord GetSymbol(int index)
        {
            // Since DictionaryCache is allowing only single thread to call this function, we don't need to lock reader here.
            SymbolReference reference = references[index];

            Reader.Position = reference.DataOffset;
            switch (reference.Kind)
            {
            case SymbolRecordKind.S_GPROC32:
            case SymbolRecordKind.S_LPROC32:
            case SymbolRecordKind.S_GPROC32_ID:
            case SymbolRecordKind.S_LPROC32_ID:
            case SymbolRecordKind.S_LPROC32_DPC:
            case SymbolRecordKind.S_LPROC32_DPC_ID:
                return(ProcedureSymbol.Read(Reader, reference.Kind));

            case SymbolRecordKind.S_PUB32:
                return(Public32Symbol.Read(Reader, reference.Kind));

            case SymbolRecordKind.S_CONSTANT:
            case SymbolRecordKind.S_MANCONSTANT:
                return(ConstantSymbol.Read(Reader, reference.Kind));

            case SymbolRecordKind.S_LDATA32:
            case SymbolRecordKind.S_GDATA32:
            case SymbolRecordKind.S_LMANDATA:
            case SymbolRecordKind.S_GMANDATA:
                return(DataSymbol.Read(Reader, reference.Kind));

            case SymbolRecordKind.S_PROCREF:
            case SymbolRecordKind.S_LPROCREF:
                return(ProcedureReferenceSymbol.Read(Reader, reference.Kind));

            case SymbolRecordKind.S_UDT:
            case SymbolRecordKind.S_COBOLUDT:
                return(UdtSymbol.Read(Reader, reference.Kind));

            case SymbolRecordKind.S_LTHREAD32:
            case SymbolRecordKind.S_GTHREAD32:
                return(ThreadLocalDataSymbol.Read(Reader, reference.Kind));

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #5
0
    public void visit(ProcDecl procDecl)
    {
        if (scope.scopeLevel == Dictionary.MAX_NEST_LEVEL)
        {
            throw new Exception(Dictionary.max_nest_level_exc);
        }
        ProcedureSymbol procSym = new ProcedureSymbol(procDecl.name);

        scope.define(procSym);
        scope = new ScopeSymbolTable(scope.scopeLevel + 1, scope);
        foreach (Param param in procDecl.parameters)
        {
            VarSymbol paramSymbol = createParamSymbol(param);
            scope.define(paramSymbol);
            procSym.parameters.Add(paramSymbol);
        }
        foreach (IAST child in procDecl.children)
        {
            child.accept(this);
        }
        scope = scope.globalScope;
    }
Beispiel #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbFunction"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="procedure">Procedure symbol record.</param>
 internal PdbFunction(PdbFileReader pdb, ProcedureSymbol procedure)
 {
     Pdb       = pdb;
     Procedure = procedure;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFileReader"/> class.
        /// </summary>
        /// <param name="pdbFile">Opened PDB file.</param>
        private PdbFileReader(PdbFile pdbFile)
        {
            PdbFile               = pdbFile;
            typesByIndex          = new DictionaryCache <TypeIndex, PdbType>(CreateType);
            userDefinedTypesCache = SimpleCache.CreateStruct(() =>
            {
                List <PdbType> types        = new List <PdbType>();
                var references              = PdbFile.TpiStream.References;
                TypeLeafKind[] allowedKinds = ClassRecord.Kinds.Concat(UnionRecord.Kinds).Concat(EnumRecord.Kinds).ToArray();

                for (int i = 0; i < references.Count; i++)
                {
                    if (allowedKinds.Contains(references[i].Kind))
                    {
                        TypeIndex typeIndex   = TypeIndex.FromArrayIndex(i);
                        TypeRecord typeRecord = PdbFile.TpiStream[typeIndex];
                        PdbType pdbType       = typesByIndex[typeIndex];

                        if (typeRecord is TagRecord tagRecord)
                        {
                            // Check if it is forward reference and if it has been resolved.
                            PdbUserDefinedType pdbUserDefinedType = (PdbUserDefinedType)pdbType;

                            if (pdbUserDefinedType.TagRecord != tagRecord)
                            {
                                continue;
                            }
                        }
                        types.Add(pdbType);
                    }
                }
                return((IReadOnlyList <PdbType>)types);
            });
            globalVarablesCache = SimpleCache.CreateStruct(() =>
            {
                var data = PdbFile.GlobalsStream.Data;
                PdbGlobalVariable[] globalVariables = new PdbGlobalVariable[data.Count];

                for (int i = 0; i < data.Count; i++)
                {
                    globalVariables[i] = new PdbGlobalVariable(this, data[i]);
                }
                return(globalVariables);
            });
            publicSymbolsCache = SimpleCache.CreateStruct(() =>
            {
                PdbPublicSymbol[] publicSymbols = new PdbPublicSymbol[PdbFile.PublicsStream.PublicSymbols.Count];

                for (int i = 0; i < publicSymbols.Length; i++)
                {
                    publicSymbols[i] = new PdbPublicSymbol(this, PdbFile.PublicsStream.PublicSymbols[i]);
                }
                return(publicSymbols);
            });
            functionsCache = SimpleCache.CreateStruct(() =>
            {
                List <PdbFunction> functions = new List <PdbFunction>();
                var references = PdbFile.PdbSymbolStream?.References;
                var modules    = PdbFile.DbiStream?.Modules;

                if (references != null && modules != null)
                {
                    HashSet <uint>[] selectedFunctions = new HashSet <uint> [modules.Count];

                    for (int i = 0; i < references.Count; i++)
                    {
                        ProcedureSymbol procedure = null;

                        switch (references[i].Kind)
                        {
                        // ProcedureSymbol
                        case SymbolRecordKind.S_GPROC32:
                        case SymbolRecordKind.S_LPROC32:
                        case SymbolRecordKind.S_GPROC32_ID:
                        case SymbolRecordKind.S_LPROC32_ID:
                        case SymbolRecordKind.S_LPROC32_DPC:
                        case SymbolRecordKind.S_LPROC32_DPC_ID:
                            procedure = PdbFile.PdbSymbolStream[i] as ProcedureSymbol;
                            break;

                        // ProcedureReferenceSymbol
                        case SymbolRecordKind.S_PROCREF:
                        case SymbolRecordKind.S_LPROCREF:
                            {
                                ProcedureReferenceSymbol procedureReference = PdbFile.PdbSymbolStream[i] as ProcedureReferenceSymbol;
                                int moduleIndex = procedureReference.Module - 1;

                                if (moduleIndex >= 0 && moduleIndex < modules.Count)
                                {
                                    var module = modules[moduleIndex];

                                    if (selectedFunctions[moduleIndex] == null)
                                    {
                                        selectedFunctions[moduleIndex] = new HashSet <uint>();
                                    }
                                    if (!selectedFunctions[moduleIndex].Contains(procedureReference.Offset) &&
                                        module.LocalSymbolStream.TryGetSymbolRecordByOffset(procedureReference.Offset, out SymbolRecord procedureSymbol))
                                    {
                                        procedure = procedureSymbol as ProcedureSymbol;
                                        selectedFunctions[moduleIndex].Add(procedureReference.Offset);
                                    }
                                }
                            }
                            break;
                        }

                        if (procedure != null)
                        {
                            functions.Add(new PdbFunction(this, procedure));
                        }
                    }
                }
                return(functions);
            });
        }
Beispiel #8
0
        /// <summary>
        /// Reads symbol record from symbol references for the specified index.
        /// </summary>
        /// <param name="index">Index of the symbol record.</param>
        private SymbolRecord GetSymbol(int index)
        {
            // Since DictionaryCache is allowing only single thread to call this function, we don't need to lock reader here.
            SymbolRecordReference reference = references[index];

            Reader.Position = reference.DataOffset;
            switch (reference.Kind)
            {
            case SymbolRecordKind.S_GPROC32:
            case SymbolRecordKind.S_LPROC32:
            case SymbolRecordKind.S_GPROC32_ID:
            case SymbolRecordKind.S_LPROC32_ID:
            case SymbolRecordKind.S_LPROC32_DPC:
            case SymbolRecordKind.S_LPROC32_DPC_ID:
                return(ProcedureSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_PUB32:
                return(Public32Symbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_CONSTANT:
            case SymbolRecordKind.S_MANCONSTANT:
                return(ConstantSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_LDATA32:
            case SymbolRecordKind.S_GDATA32:
            case SymbolRecordKind.S_LMANDATA:
            case SymbolRecordKind.S_GMANDATA:
                return(DataSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_PROCREF:
            case SymbolRecordKind.S_LPROCREF:
                return(ProcedureReferenceSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_TOKENREF:
                return(TokenReferenceSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_UDT:
            case SymbolRecordKind.S_COBOLUDT:
                return(UdtSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_LTHREAD32:
            case SymbolRecordKind.S_GTHREAD32:
                return(ThreadLocalDataSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_GMANPROC:
            case SymbolRecordKind.S_LMANPROC:
                return(ManagedProcedureSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_BLOCK32:
                return(BlockSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_OEM:
                return(OemSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_UNAMESPACE:
                return(NamespaceSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_MANSLOT:
                return(AttributeSlotSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_END:
            case SymbolRecordKind.S_INLINESITE_END:
                return(EndSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_ANNOTATION:
                return(AnnotationSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_ANNOTATIONREF:
                return(AnnotationReferenceSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_REGREL32:
                return(RegisterRelativeSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_OBJNAME:
                return(ObjectNameSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_COMPILE2:
                return(Compile2Symbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_COMPILE3:
                return(Compile3Symbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_ENVBLOCK:
                return(EnvironmentBlockSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_BUILDINFO:
                return(BuildInfoSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_FRAMEPROC:
                return(FrameProcedureSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_LABEL32:
                return(LabelSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_HEAPALLOCSITE:
                return(HeapAllocationSiteSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_CALLSITEINFO:
                return(CallSiteInfoSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_FRAMECOOKIE:
                return(FrameCookieSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_THUNK32:
                return(Thunk32Symbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_LOCAL:
                return(LocalSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_DEFRANGE_REGISTER:
                return(DefRangeRegisterSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_DEFRANGE_REGISTER_REL:
                return(DefRangeRegisterRelativeSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_DEFRANGE_SUBFIELD_REGISTER:
                return(DefRangeSubfieldRegisterSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_DEFRANGE_FRAMEPOINTER_REL:
                return(DefRangeFramePointerRelativeSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
                return(DefRangeFramePointerRelativeFullScopeSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_CALLEES:
            case SymbolRecordKind.S_CALLERS:
                return(FunctionListSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            case SymbolRecordKind.S_FILESTATIC:
                return(FileStaticSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_TRAMPOLINE:
                return(TrampolineSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_SECTION:
                return(SectionSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_COFFGROUP:
                return(CoffGroupSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_EXPORT:
                return(ExportSymbol.Read(Reader, this, index, reference.Kind));

            case SymbolRecordKind.S_INLINESITE:
                return(InlineSiteSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen));

            default:
#if DEBUG
                throw new NotImplementedException($"Unknown reference kind: {reference.Kind}");
#else
                return(null);
#endif
            }
        }