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; }
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 } }
/// <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(); } }
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; }
/// <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); }); }
/// <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 } }