/* add this function to the code center. it better not be in there already */ public void AddFunctionToCodeCenter(FuncCodeRec TheNewFunction, object Signature) { if (CodeCenterHaveThisFunction(TheNewFunction.GetFunctionName())) { // function is already in the database Debug.Assert(false); throw new ArgumentException(); } CodeList.Add(new CodeEntryRec(Signature, TheNewFunction)); // add managed reference if (TheNewFunction.CILObject != null) { ManagedFunctionLinker.LinkFunctionName( TheNewFunction.GetFunctionName(), TheNewFunction.CILObject.MethodInfo, TheNewFunction.GetFunctionParameterTypeList(), TheNewFunction.GetFunctionReturnType()); } }
public PcodeEvaluationErrorInfo(EvalErrors EvaluationError, EvalErrInfoRec ErrorInfo, PcodeRec AnonymousFunction, CodeCenterRec CodeCenter) { int ErrorLineNumberEvaluation; string Name; FuncCodeRec ErrorFunction = CodeCenter.GetFunctionFromOpcode(ErrorInfo.OffendingPcode); if (ErrorFunction != null) { Name = ErrorFunction.GetFunctionFilename(); ErrorLineNumberEvaluation = ErrorFunction.GetFunctionPcode().GetLineNumberForInstruction(ErrorInfo.OffendingInstruction); } else { Name = "<anonymous>"; ErrorLineNumberEvaluation = AnonymousFunction.GetLineNumberForInstruction(ErrorInfo.OffendingInstruction); } this.module = Name; this.errorText = PcodeSystem.GetPcodeErrorMessage(EvaluationError); this.lineNumber = ErrorLineNumberEvaluation; }
public CodeEntryRec(object Signature, FuncCodeRec Function) { this.Signature = Signature; this.Function = Function; }
/* shared initialization */ private static SynthErrorCodes UserEffectSharedInit( UserEffectProcRec Proc, UserEffectSpecRec Template, SynthParamRec SynthParams) { Proc.disableOversampling = GetUserEffectSpecNoOversampling(Template); double sr = SynthParams.dSamplingRate; if (!((SynthParams.iOversampling == 1) || !Proc.disableOversampling)) { sr /= SynthParams.iOversampling; } /* init func */ { string FuncName = GetUserEffectSpecInitFuncName(Template); if (FuncName != null) { FuncCodeRec FuncCode = SynthParams.CodeCenter.ObtainFunctionHandle(FuncName); if (FuncCode == null) { // Function missing; should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } DataTypes[] argsTypes; DataTypes returnType; UserEffectGetInitSignature(Template, out argsTypes, out returnType); FunctionSignature expectedSignature = new FunctionSignature(argsTypes, returnType); FunctionSignature actualSignature = new FunctionSignature( FuncCode.GetFunctionParameterTypeList(), FuncCode.GetFunctionReturnType()); if (!FunctionSignature.Equals(expectedSignature, actualSignature)) { // Function type mismatch; should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } Proc.InitFunc = FuncCode.GetFunctionPcode(); } } /* data func */ { DataTypes[] argsTypes; DataTypes returnType; UserEffectGetDataSignature(Template, out argsTypes, out returnType); FunctionSignature expectedSignature = new FunctionSignature(argsTypes, returnType); foreach (string FuncName in GetUserEffectSpecProcessDataFuncNames(Template)) { FuncCodeRec FuncCode = SynthParams.CodeCenter.ObtainFunctionHandle(FuncName); if (FuncCode == null) { // Function missing; should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } FunctionSignature actualSignature = new FunctionSignature( FuncCode.GetFunctionParameterTypeList(), FuncCode.GetFunctionReturnType()); if (FunctionSignature.Equals(expectedSignature, actualSignature)) { Proc.DataFunc = FuncCode.GetFunctionPcode(); break; } } if (Proc.DataFunc == null) { // None matched -- should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } } Proc.paramCount = GetUserEffectSpecParamCount(Template); Proc.paramResults = new double[Proc.paramCount]; Proc.paramResultsPrevious = new double[Proc.paramCount]; // create state objects DataTypes[] stateTypes = UserEffectGetWorkspaceTypes(Template); Proc.userState = new ArrayHandle[stateTypes.Length]; for (int i = 0; i < Proc.userState.Length; i++) { switch (stateTypes[i]) { default: Debug.Assert(false); throw new ArgumentException(); case DataTypes.eArrayOfInteger: Proc.userState[i] = new ArrayHandleInt32(new int[0]); break; case DataTypes.eArrayOfFloat: Proc.userState[i] = new ArrayHandleFloat(new float[0]); break; case DataTypes.eArrayOfDouble: Proc.userState[i] = new ArrayHandleDouble(new double[0]); break; } } Proc.smoothingBuffers = new SmoothingEntry[Template.Items.Length]; for (int i = 0; i < Template.Items.Length; i++) { if (Template.Items[i].Smoothed) { float[] vector = new float[SynthParams.nAllocatedPointsOneChannel]; Proc.smoothingBuffers[i].vector = vector; Proc.smoothingBuffers[i].arrayHandle = new ArrayHandleFloat(vector); } } /* initialize user state */ if (Proc.InitFunc != null) { int argCount = 1 /*retval*/ + 1 /*t*/ + 1 /*bpm*/ + 1 /*samplingRate*/ + 1 /*maxSampleCount*/ + Proc.userState.Length /*user state arrays*/ + 1 /*retaddr*/; SynthParams.FormulaEvalContext.EmptyParamStackEnsureCapacity(argCount); StackElement[] StackBase; int StackNumElements; SynthParams.FormulaEvalContext.GetRawStack(out StackBase, out StackNumElements); StackBase[StackNumElements++].Data.Double = SynthParams.dElapsedTimeInSeconds; /* t */ StackBase[StackNumElements++].Data.Double = SynthParams.dCurrentBeatsPerMinute; /* bpm */ StackBase[StackNumElements++].Data.Double = sr; /* samplingRate */ StackBase[StackNumElements++].Data.Integer = SynthParams.nAllocatedPointsOneChannel; /* maxSampleCount */ for (int i = 0; i < Proc.userState.Length; i++) { StackBase[StackNumElements++].reference.arrayHandleGeneric = Proc.userState[i]; // user state } StackNumElements++; /* return address placeholder */ SynthParams.FormulaEvalContext.UpdateRawStack(StackBase, StackNumElements); EvalErrInfoRec ErrorInfo; EvalErrors Error = PcodeSystem.EvaluatePcode( SynthParams.FormulaEvalContext, Proc.InitFunc, SynthParams.CodeCenter, out ErrorInfo, PcodeExternsNull.Default, ref SynthParams.pcodeThreadContext); if (Error != EvalErrors.eEvalNoError) { SynthParams.ErrorInfo.ErrorEx = SynthErrorSubCodes.eSynthErrorExUserEffectFunctionEvalError; SynthParams.ErrorInfo.UserEvalErrorCode = Error; SynthParams.ErrorInfo.UserEvalErrorInfo = ErrorInfo; return(SynthErrorCodes.eSynthErrorEx); } Debug.Assert(SynthParams.FormulaEvalContext.GetStackNumElements() == 1); // return value SynthParams.FormulaEvalContext.Clear(); } // initialize sample data in/out staging areas Proc.leftWorkspace = new float[SynthParams.nAllocatedPointsOneChannel]; Proc.leftWorkspaceHandle = new ArrayHandleFloat(null); Proc.rightWorkspace = new float[SynthParams.nAllocatedPointsOneChannel]; Proc.rightWorkspaceHandle = new ArrayHandleFloat(null); return(SynthErrorCodes.eSynthDone); }
// Compile multiple modules. (eliminates the need to do prototyping or function signature inference.) // CodeCenter is cleared, and if compilation succeeds, the functions are added to CodeCenter. public static CompileErrors CompileWholeProgram( out int ErrorLineNumber, out int ErrorModuleIndex, string[] TextDatas, object[] Signatures, CodeCenterRec CodeCenter, string[] Filenames) { Debug.Assert(TextDatas.Length == Signatures.Length); Debug.Assert(TextDatas.Length == Filenames.Length); ErrorLineNumber = -1; ErrorModuleIndex = -1; CodeCenter.FlushAllCompiledFunctions(); CodeCenter.RetainedFunctionSignatures = new KeyValuePair <string, FunctionSignature> [0]; // parse List <SymbolRec> SymbolTableEntriesForForm = new List <SymbolRec>(); List <ASTExpression> FunctionBodyRecords = new List <ASTExpression>(); List <int> ModuleIndices = new List <int>(); Dictionary <string, List <ParserContext.FunctionSymbolRefInfo> > FunctionRefSymbolList = new Dictionary <string, List <ParserContext.FunctionSymbolRefInfo> >(); List <int> InitialLineNumbersOfForm = new List <int>(); for (int module = 0; module < TextDatas.Length; module++) { string TextData = TextDatas[module]; ErrorModuleIndex = module; ScannerRec <KeywordsType> TheScanner = new ScannerRec <KeywordsType>(TextData, KeywordTable); SymbolTableRec TheSymbolTable = new SymbolTableRec(); /* loop until there are no more things to parse */ while (true) { TokenRec <KeywordsType> Token = TheScanner.GetNextToken(); int InitialLineNumberOfForm = TheScanner.GetCurrentLineNumber(); if (Token.GetTokenType() == TokenTypes.eTokenEndOfInput) { /* no more functions to parse, so stop */ break; } SymbolRec SymbolTableEntryForForm; ASTExpression FunctionBodyRecord; /* parse the function */ TheScanner.UngetToken(Token); CompileErrors Error = ParseForm( out SymbolTableEntryForForm, out FunctionBodyRecord, new ParserContext( TheScanner, TheSymbolTable, FunctionRefSymbolList), out ErrorLineNumber); if (Error != CompileErrors.eCompileNoError) { return(Error); } Debug.Assert(FunctionBodyRecord != null); ModuleIndices.Add(module); SymbolTableEntriesForForm.Add(SymbolTableEntryForForm); FunctionBodyRecords.Add(FunctionBodyRecord); InitialLineNumbersOfForm.Add(InitialLineNumberOfForm); } foreach (KeyValuePair <string, List <ParserContext.FunctionSymbolRefInfo> > name in FunctionRefSymbolList) { foreach (ParserContext.FunctionSymbolRefInfo funcRef in name.Value) { funcRef.module = module; } } } // push function type signatures into function call refs Dictionary <string, bool> functionNamesUsed = new Dictionary <string, bool>(); for (int i = 0; i < SymbolTableEntriesForForm.Count; i++) { ErrorModuleIndex = ModuleIndices[i]; SymbolRec FunctionDeclarationSymbol = SymbolTableEntriesForForm[i]; if (functionNamesUsed.ContainsKey(FunctionDeclarationSymbol.SymbolName)) { ErrorLineNumber = FunctionBodyRecords[i].LineNumber; return(CompileErrors.eCompileMultiplyDeclaredFunction); } functionNamesUsed.Add(FunctionDeclarationSymbol.SymbolName, false); List <ParserContext.FunctionSymbolRefInfo> symbols; if (FunctionRefSymbolList.TryGetValue(FunctionDeclarationSymbol.SymbolName, out symbols)) { foreach (ParserContext.FunctionSymbolRefInfo functionRef in symbols) { functionRef.symbol.SymbolBecomeFunction2( FunctionDeclarationSymbol.FunctionArgList, FunctionDeclarationSymbol.FunctionReturnType); } FunctionRefSymbolList.Remove(FunctionDeclarationSymbol.SymbolName); } } foreach (KeyValuePair <string, List <ParserContext.FunctionSymbolRefInfo> > name in FunctionRefSymbolList) { foreach (ParserContext.FunctionSymbolRefInfo funcRef in name.Value) { ErrorModuleIndex = funcRef.module; ErrorLineNumber = funcRef.lineNumber; return(CompileErrors.eCompileMultiplyDeclaredFunction); } } // type check and type inference for (int i = 0; i < FunctionBodyRecords.Count; i++) { int module = ModuleIndices[i]; SymbolRec SymbolTableEntryForForm = SymbolTableEntriesForForm[i]; ASTExpression FunctionBodyRecord = FunctionBodyRecords[i]; int InitialLineNumberOfForm = InitialLineNumbersOfForm[i]; ErrorModuleIndex = module; /* SymbolTableEntryForForm will be the symbol table entry that */ /* was added to the symbol table. FunctionBodyRecord is either */ /* an expression for a function or NIL if it was a prototype */ Debug.Assert(!CodeCenter.CodeCenterHaveThisFunction(SymbolTableEntryForForm.SymbolName)); /* step 1: do type checking */ DataTypes ResultingType; CompileErrors Error = FunctionBodyRecord.TypeCheck( out ResultingType, out ErrorLineNumber); if (Error != CompileErrors.eCompileNoError) { return(Error); } /* check to see that resulting type matches declared type */ if (!CanRightBeMadeToMatchLeft(SymbolTableEntryForForm.FunctionReturnType, ResultingType)) { ErrorLineNumber = InitialLineNumberOfForm; return(CompileErrors.eCompileTypeMismatch); } /* if it has to be promoted, then promote it */ if (MustRightBePromotedToLeft(SymbolTableEntryForForm.FunctionReturnType, ResultingType)) { /* insert promotion operator above expression */ ASTExpression ReplacementExpr = PromoteTheExpression( ResultingType, SymbolTableEntryForForm.FunctionReturnType, FunctionBodyRecord, InitialLineNumberOfForm); FunctionBodyRecord = ReplacementExpr; /* sanity check */ Error = FunctionBodyRecord.TypeCheck( out ResultingType, out ErrorLineNumber); if (Error != CompileErrors.eCompileNoError) { // type promotion caused failure Debug.Assert(false); throw new InvalidOperationException(); } if (ResultingType != SymbolTableEntryForForm.FunctionReturnType) { // after type promotion, types are no longer the same Debug.Assert(false); throw new InvalidOperationException(); } } } // code generation CILAssembly cilAssembly = null; if (CILObject.EnableCIL) { cilAssembly = new CILAssembly(); } FuncCodeRec[] TheWholeFunctionThings = new FuncCodeRec[FunctionBodyRecords.Count]; for (int i = 0; i < FunctionBodyRecords.Count; i++) { int module = ModuleIndices[i]; SymbolRec SymbolTableEntryForForm = SymbolTableEntriesForForm[i]; ASTExpression FunctionBodyRecord = FunctionBodyRecords[i]; int InitialLineNumberOfForm = InitialLineNumbersOfForm[i]; string Filename = Filenames[module]; object Signature = Signatures[module]; ErrorModuleIndex = module; Debug.Assert(!CodeCenter.CodeCenterHaveThisFunction(SymbolTableEntryForForm.SymbolName)); /* step 1.5: optimize the AST */ OptimizeAST(ref FunctionBodyRecord); /* step 2: do code generation */ /* calling conventions: */ /* - push the arguments */ /* - funccall pushes the return address */ /* thus, upon entry, Stack[0] will be the return address */ /* and Stack[-1] will be the rightmost argument */ /* on return, args and retaddr are popped and retval replaces them */ int StackDepth = 0; int MaxStackDepth = 0; int ReturnValueLocation = StackDepth; /* remember return value location */ int ArgumentIndex = 0; SymbolListRec FormalArgumentListScan = SymbolTableEntryForForm.FunctionArgList; while (FormalArgumentListScan != null) { SymbolRec TheFormalArg = FormalArgumentListScan.First; StackDepth++; /* allocate first */ MaxStackDepth = Math.Max(MaxStackDepth, StackDepth); TheFormalArg.SymbolVariableStackLocation = StackDepth; /* remember */ ArgumentIndex++; FormalArgumentListScan = FormalArgumentListScan.Rest; } /* reserve return address spot */ StackDepth++; MaxStackDepth = Math.Max(MaxStackDepth, StackDepth); /* allocate the function code */ PcodeRec TheFunctionCode = new PcodeRec(); FunctionBodyRecord.PcodeGen( TheFunctionCode, ref StackDepth, ref MaxStackDepth); Debug.Assert(StackDepth <= MaxStackDepth); /* 2 extra words for retaddr and resultofexpr */ if (StackDepth != ArgumentIndex + 1 + 1) { // stack depth error after evaluating function Debug.Assert(false); throw new InvalidOperationException(); } /* now put the return instruction (pops retaddr and args, leaving retval) */ int ignored; TheFunctionCode.AddPcodeInstruction(Pcodes.epReturnFromSubroutine, out ignored, InitialLineNumberOfForm); TheFunctionCode.AddPcodeOperandInteger(ArgumentIndex); StackDepth = StackDepth - (1 + ArgumentIndex); Debug.Assert(StackDepth <= MaxStackDepth); if (StackDepth != 1) { // stack depth is wrong at end of function Debug.Assert(false); throw new InvalidOperationException(); } TheFunctionCode.MaxStackDepth = MaxStackDepth; /* step 2.5: optimize the code */ TheFunctionCode.OptimizePcode(); /* step 3: create the function and save it away */ FuncCodeRec TheWholeFunctionThing = new FuncCodeRec( SymbolTableEntryForForm.SymbolName, SymbolTableEntryForForm.FunctionArgList, TheFunctionCode, SymbolTableEntryForForm.FunctionReturnType, Filename); TheWholeFunctionThings[i] = TheWholeFunctionThing; if (CILObject.EnableCIL) { DataTypes[] argsTypes; string[] argsNames; SymbolicArgListToType(SymbolTableEntryForForm, out argsTypes, out argsNames); CILObject cilObject = new CILObject( CodeCenter.ManagedFunctionLinker, argsTypes, argsNames, SymbolTableEntryForForm.FunctionReturnType, FunctionBodyRecord, cilAssembly, false /*argsByRef*/); TheWholeFunctionThing.CILObject = cilObject; } } // register after entire assembly is emitted if (CILObject.EnableCIL) { cilAssembly.Finish(); } for (int i = 0; i < TheWholeFunctionThings.Length; i++) { FuncCodeRec TheWholeFunctionThing = TheWholeFunctionThings[i]; object Signature = Signatures[ModuleIndices[i]]; CodeCenter.AddFunctionToCodeCenter(TheWholeFunctionThing, Signature); } // retain signatures for compilation of special functions CodeCenter.RetainedFunctionSignatures = new KeyValuePair <string, FunctionSignature> [SymbolTableEntriesForForm.Count]; for (int i = 0; i < CodeCenter.RetainedFunctionSignatures.Length; i++) { DataTypes[] argsTypes; string[] argsNames; SymbolicArgListToType(SymbolTableEntriesForForm[i], out argsTypes, out argsNames); CodeCenter.RetainedFunctionSignatures[i] = new KeyValuePair <string, FunctionSignature>( SymbolTableEntriesForForm[i].SymbolName, new FunctionSignature( argsTypes, SymbolTableEntriesForForm[i].FunctionReturnType)); } return(CompileErrors.eCompileNoError); }
/* check user effect */ public static SynthErrorCodes CheckUserEffectForUnreferencedSamples( UserEffectSpecRec UserEffect, CheckUnrefParamRec Param) { /* init func */ { string FuncName = GetUserEffectSpecInitFuncName(UserEffect); if (FuncName != null) /* optional */ { FuncCodeRec FuncCode = Param.CodeCenter.ObtainFunctionHandle(FuncName); if (FuncCode == null) { Param.ErrorInfo.ErrorEx = SynthErrorSubCodes.eSynthErrorExUndefinedFunction; Param.ErrorInfo.FunctionName = FuncName; return(SynthErrorCodes.eSynthErrorEx); } DataTypes[] argsTypes; DataTypes returnType; UserEffectGetInitSignature(UserEffect, out argsTypes, out returnType); FunctionSignature expectedSignature = new FunctionSignature(argsTypes, returnType); FunctionSignature actualSignature = new FunctionSignature( FuncCode.GetFunctionParameterTypeList(), FuncCode.GetFunctionReturnType()); if (!FunctionSignature.Equals(expectedSignature, actualSignature)) { Param.ErrorInfo.ErrorEx = SynthErrorSubCodes.eSynthErrorExTypeMismatchFunction; Param.ErrorInfo.FunctionName = FuncName; Param.ErrorInfo.ExtraInfo = String.Format( "{0}{0}Expected:{0}{1}{0}{0}Actual:{0}{2}", Environment.NewLine, expectedSignature, actualSignature); return(SynthErrorCodes.eSynthErrorEx); } } } /* data func */ { DataTypes[] argsTypes; DataTypes returnType; UserEffectGetDataSignature(UserEffect, out argsTypes, out returnType); FunctionSignature expectedSignature = new FunctionSignature(argsTypes, returnType); bool matched = false; List <KeyValuePair <string, FunctionSignature> > actualSignatures = new List <KeyValuePair <string, FunctionSignature> >(); foreach (string FuncName in GetUserEffectSpecProcessDataFuncNames(UserEffect)) { FuncCodeRec FuncCode = Param.CodeCenter.ObtainFunctionHandle(FuncName); if (FuncCode == null) { Param.ErrorInfo.ErrorEx = SynthErrorSubCodes.eSynthErrorExUndefinedFunction; Param.ErrorInfo.FunctionName = FuncName; return(SynthErrorCodes.eSynthErrorEx); } FunctionSignature actualSignature = new FunctionSignature( FuncCode.GetFunctionParameterTypeList(), FuncCode.GetFunctionReturnType()); actualSignatures.Add(new KeyValuePair <string, FunctionSignature>(FuncName, actualSignature)); if (FunctionSignature.Equals(expectedSignature, actualSignature)) { matched = true; break; } } if (!matched) { StringBuilder extraInfo = new StringBuilder(); extraInfo.AppendLine(); extraInfo.AppendLine(); extraInfo.AppendLine(String.Format("Expected - {0}", expectedSignature)); foreach (KeyValuePair <string, FunctionSignature> actualSignature in actualSignatures) { extraInfo.AppendLine(); extraInfo.AppendLine(String.Format("Actual - {0}{1}", actualSignature.Key, actualSignature.Value)); } Param.ErrorInfo.ErrorEx = SynthErrorSubCodes.eSynthErrorExTypeMismatchFunctionMultiple; Param.ErrorInfo.ExtraInfo = extraInfo.ToString(); return(SynthErrorCodes.eSynthErrorEx); } } return(SynthErrorCodes.eSynthDone); }