public void Traverse(CParser.Node Node) { if (TraverseHook == null) { TraverseHook = delegate(Action _Action, CParser.Node _ParentNode, CParser.Node _Node) { _Action(); } } ; TraverseHook(() => { Scopable.RefScope(ref ParentNode, Node, () => { if (Node != null) { var NodeType = Node.GetType(); if (Map.ContainsKey(NodeType)) { Map[NodeType].Invoke(TargetObject, new object[] { Node }); } else { throw (new NotImplementedException(String.Format("Not implemented {0}", Node.GetType()))); } } }); }, ParentNode, Node); }
/// <summary> /// /// </summary> /// <param name="BaseWhileStatement"></param> /// <param name="ExecuteAtLeastOnce"></param> private void BaseWhileStatement(CParser.BaseWhileStatement BaseWhileStatement, bool ExecuteAtLeastOnce) { PutDebugLine(BaseWhileStatement); var IterationLabel = SafeILGenerator.DefineLabel("IterationLabel"); var BreakLabel = SafeILGenerator.DefineLabel("BreakLabel"); var ContinueLabel = SafeILGenerator.DefineLabel("ContinueLabel"); var LoopCheckConditionLabel = SafeILGenerator.DefineLabel("LoopCheckConditionLabel"); if (!ExecuteAtLeastOnce) { SafeILGenerator.BranchAlways(LoopCheckConditionLabel); } IterationLabel.Mark(); Scopable.RefScope(ref BreakableContext, new LabelContext(BreakLabel), () => { Scopable.RefScope(ref ContinuableContext, new LabelContext(ContinueLabel), () => { Traverse(BaseWhileStatement.LoopStatements); }); }); ContinueLabel.Mark(); LoopCheckConditionLabel.Mark(); Traverse(BaseWhileStatement.Condition); SafeILGenerator.BranchIfTrue(IterationLabel); BreakLabel.Mark(); }
public void SetText(string FileName, string NewText, Action Action) { Scopable.RefScope(ref this.Text, NewText, () => { Scopable.RefScope(ref this.FileName, FileName, () => { Action(); }); }); }
public void SwitchStatement(CParser.SwitchStatement SwitchStatement) { PutDebugLine(SwitchStatement); SafeILGenerator.SaveRestoreTypeStack(() => { // TODO: improve speed with tables and proper switch instead of lot of "if" checks. var MapLabels = new Dictionary <int, SafeLabel>(); var DefaultLabel = SafeILGenerator.DefineLabel("SwitchDefault"); var EndLabel = SafeILGenerator.DefineLabel("SwitchEnd"); //var SwitchExpressionLocal = SafeILGenerator.DeclareLocal<long>("SwitchReference"); //SafeILGenerator.LoadLocal(SwitchExpressionLocal); //foreach (var SwitchCaseStatement in SwitchStatement.Statements.Statements.Where(Item => Item is CParser.SwitchCaseStatement).Cast<CParser.SwitchCaseStatement>()) foreach (var Statement in SwitchStatement.Statements.Statements) { var SwitchCaseStatement = Statement as CParser.SwitchCaseStatement; var SwitchDefaultStatement = Statement as CParser.SwitchDefaultStatement; if (SwitchCaseStatement != null) { var Value = SwitchCaseStatement.Value.GetConstantValue <int>(null); var CaseLabel = SafeILGenerator.DefineLabel("SwitchCase"); SwitchCaseStatement.Tag = CaseLabel; //Console.WriteLine("Value: {0}", Value); MapLabels.Add(Value, CaseLabel); } else if (SwitchDefaultStatement != null) { SwitchDefaultStatement.Tag = DefaultLabel; } } Traverse(SwitchStatement.ReferenceExpression); SafeILGenerator.Switch(MapLabels, DefaultLabel); Scopable.RefScope(ref BreakableContext, new LabelContext(EndLabel), () => { Traverse(SwitchStatement.Statements); }); if (!DefaultLabel.Marked) { DefaultLabel.Mark(); } EndLabel.Mark(); }); }
public void ForStatement(CParser.ForStatement ForStatement) { PutDebugLine(ForStatement); if (ForStatement.Init != null) { Traverse(ForStatement.Init); SafeILGenerator.PopLeft(); } var IterationLabel = SafeILGenerator.DefineLabel("IterationLabel"); var BreakLabel = SafeILGenerator.DefineLabel("BreakLabel"); var ContinueLabel = SafeILGenerator.DefineLabel("ContinueLabel"); var LoopCheckConditionLabel = SafeILGenerator.DefineLabel("LoopCheckConditionLabel"); { SafeILGenerator.BranchAlways(LoopCheckConditionLabel); IterationLabel.Mark(); Scopable.RefScope(ref BreakableContext, new LabelContext(BreakLabel), () => { Scopable.RefScope(ref ContinuableContext, new LabelContext(ContinueLabel), () => { Traverse(ForStatement.LoopStatements); }); }); ContinueLabel.Mark(); if (ForStatement.PostOperation != null) { Traverse(ForStatement.PostOperation); SafeILGenerator.PopLeft(); } LoopCheckConditionLabel.Mark(); if (ForStatement.Condition != null) { Traverse(ForStatement.Condition); } else { SafeILGenerator.Push(1); } SafeILGenerator.BranchIfTrue(IterationLabel); BreakLabel.Mark(); } }
/// <summary> /// /// </summary> /// <param name="Set"></param> /// <param name="Action"></param> private void DoGenerateAddress(bool Set, Action Action) { Scopable.RefScope(ref this.GenerateAddress, Set, Action); }
public void FunctionDeclaration(CParser.FunctionDeclaration FunctionDeclaration) { PutDebugLine(FunctionDeclaration); var FunctionName = FunctionDeclaration.CFunctionType.Name; var ReturnType = ConvertCTypeToType(FunctionDeclaration.CFunctionType.Return); var ParameterTypes = FunctionDeclaration.CFunctionType.Parameters.Select(Item => ConvertCTypeToType(Item.CType)).ToArray(); var ParameterCSymbols = FunctionDeclaration.CFunctionType.Parameters; if (ParameterTypes.Length == 1 && ParameterTypes[0] == typeof(void)) { ParameterTypes = new Type[0]; } var FunctionReference = FunctionScope.Find(FunctionName); if (FunctionReference == null) { var CurrentMethodLazy = new Lazy <MethodInfo>(() => { var MethodBuilder = CurrentClass.DefineMethod( FunctionName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, ReturnType, ParameterTypes ); for (int n = 0; n < ParameterCSymbols.Length; n++) { MethodBuilder.DefineParameter(n, ParameterAttributes.None, ParameterCSymbols[n].Name); } return(MethodBuilder); }); FunctionReference = new FunctionReference(this, FunctionName, CurrentMethodLazy, new SafeMethodTypeInfo() { IsStatic = true, ReturnType = ReturnType, Parameters = ParameterTypes, }) { BodyFinalized = false, }; FunctionScope.Push(FunctionName, FunctionReference); } // Just declaration if (FunctionDeclaration.FunctionBody == null) { } // Has function body. else { var CurrentMethod = (FunctionReference.MethodInfo as MethodBuilder); if (FunctionName == "main") { //HasEntryPoint = true; var StartupMethod = CurrentClass.DefineMethod( "__startup", MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(int), new Type[] { typeof(string[]) } ); var StartupSafeILGenerator = new SafeILGenerator(StartupMethod.GetILGenerator(), CheckTypes: true, DoDebug: false, DoLog: false); var ArgsArgument = StartupSafeILGenerator.DeclareArgument(typeof(string[]), 0); StartupSafeILGenerator.Push(CurrentClass); StartupSafeILGenerator.Call((Func <RuntimeTypeHandle, Type>)Type.GetTypeFromHandle); StartupSafeILGenerator.LoadArgument(ArgsArgument); StartupSafeILGenerator.Call((Func <Type, string[], int>)CLibUtils.RunTypeMain); //StartupSafeILGenerator.Call((Func<Type, string[], int>)CLibUtils.RunTypeMain); StartupSafeILGenerator.Return(typeof(int)); EntryPoint = StartupMethod; //EntryPoint = CurrentMethod; } var ILGenerator = CurrentMethod.GetILGenerator(); var CurrentSafeILGenerator = new SafeILGenerator(ILGenerator, CheckTypes: false, DoDebug: false, DoLog: true); AScope <VariableReference> .NewScope(ref this.VariableScope, () => { Scopable.RefScope(ref this.GotoContext, new LabelsContext(CurrentSafeILGenerator), () => { Scopable.RefScope(ref this.CurrentMethod, CurrentMethod, () => { Scopable.RefScope(ref this.SafeILGenerator, CurrentSafeILGenerator, () => { // Set argument variables ushort ArgumentIndex = 0; foreach (var Parameter in FunctionDeclaration.CFunctionType.Parameters) { var Argument = SafeILGenerator.DeclareArgument(ConvertCTypeToType(Parameter.CType), ArgumentIndex); this.VariableScope.Push(Parameter.Name, new VariableReference(Parameter.Name, Parameter.CType, Argument)); ArgumentIndex++; } Traverse(FunctionDeclaration.FunctionBody); if (FunctionDeclaration.FunctionBody.Statements.Length == 0 || !(FunctionDeclaration.FunctionBody.Statements.Last() is CParser.ReturnStatement)) //if (true) { if (CurrentMethod.ReturnType != typeof(void)) { SafeILGenerator.Push((int)0); } SafeILGenerator.Return(CurrentMethod.ReturnType); } }); #if SHOW_INSTRUCTIONS Console.WriteLine("Code for '{0}':", FunctionName); foreach (var Instruction in CurrentSafeILGenerator.GetEmittedInstructions()) { Console.WriteLine(" {0}", Instruction); } #endif }); }); }); FunctionReference.BodyFinalized = true; } }
public void VariableDeclaration(CParser.VariableDeclaration VariableDeclaration) { PutDebugLine(VariableDeclaration); var VariableName = VariableDeclaration.Symbol.Name; var VariableCType = VariableDeclaration.Symbol.CType; //Console.WriteLine(VariableCType); // ?? if (VariableCType == null) { Console.Error.WriteLine("Warning: Global variable '{0}' doesn't have type!!", VariableName); return; } var VariableType = ConvertCTypeToType(VariableCType); var IsExternVariable = (VariableCType.GetCSimpleType().Storage == CTypeStorage.Extern); var IsAlreadyDefined = (VariableScope.Find(VariableName) != null); if (IsAlreadyDefined) { if (!IsExternVariable) { Console.Error.WriteLine("Warning: Global variable '{0}' already defined but not defined as external", VariableName); } return; } if (VariableName == null || VariableName.Length == 0) { Console.Error.WriteLine("Variable doesn't have name!"); return; } if (VariableCType is CFunctionType) { Console.Error.WriteLine("Variable is not a function!"); return; } if (VariableType == typeof(void)) { Console.Error.WriteLine("Variable has void type!"); return; } VariableReference Variable; bool GlobalScope; // Global Scope if (this.SafeILGenerator == null) { GlobalScope = true; var Field = CurrentClass.DefineField(VariableName, VariableType, FieldAttributes.Static | FieldAttributes.Public); Variable = new VariableReference(VariableDeclaration.Symbol.Name, VariableDeclaration.Symbol.CType, Field); } // Local Scope else { GlobalScope = false; var Local = this.SafeILGenerator.DeclareLocal(VariableType, VariableName); Variable = new VariableReference(VariableDeclaration.Symbol.Name, VariableDeclaration.Symbol.CType, Local); } this.VariableScope.Push(VariableName, Variable); Action Initialize = () => { Variable.LoadAddress(SafeILGenerator); SafeILGenerator.InitObject(VariableType); Traverse(VariableDeclaration.InitialValue); SafeILGenerator.PopLeft(); }; if (GlobalScope) { Scopable.RefScope(ref SafeILGenerator, StaticInitializerSafeILGenerator, () => { Initialize(); }); } else { Initialize(); } }
public void TranslationUnit(CParser.TranslationUnit TranslationUnit) { #if false try { #endif PutDebugLine(TranslationUnit); try { File.Delete(OutFolder + "\\" + OutputName); } catch { } var ClassName = Path.GetFileNameWithoutExtension(OutputName); this.AssemblyBuilder = SafeAssemblyUtils.CreateAssemblyBuilder(ClassName, OutFolder); this.ModuleBuilder = this.AssemblyBuilder.CreateModuleBuilder(OutputName); this.RootTypeBuilder = this.ModuleBuilder.DefineType(ClassName, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit); PendingTypesToCreate.Add(this.RootTypeBuilder); var InitializerBuilder = this.RootTypeBuilder.DefineTypeInitializer(); var CurrentStaticInitializerSafeILGenerator = new SafeILGenerator(InitializerBuilder.GetILGenerator(), CheckTypes: false, DoDebug: false, DoLog: false); Scopable.RefScope(ref this.StaticInitializerSafeILGenerator, CurrentStaticInitializerSafeILGenerator, () => { Scopable.RefScope(ref this.CurrentClass, this.RootTypeBuilder, () => { AScope <VariableReference> .NewScope(ref this.VariableScope, () => { Traverse(TranslationUnit.Declarations); this.StaticInitializerSafeILGenerator.Return(typeof(void)); //RootTypeBuilder.CreateType(); foreach (var FunctionReference in FunctionScope.GetAll()) { if (!FunctionReference.BodyFinalized && FunctionReference.HasStartedBody) { Console.WriteLine("Function {0} without body", FunctionReference.Name); var FakeSafeILGenerator = new SafeILGenerator((FunctionReference.MethodInfo as MethodBuilder).GetILGenerator(), CheckTypes: true, DoDebug: true, DoLog: false); FakeSafeILGenerator.Push(String.Format("Not implemented '{0}'", FunctionReference.Name)); FakeSafeILGenerator.NewObject(typeof(NotImplementedException).GetConstructor(new Type[] { typeof(string) })); FakeSafeILGenerator.Throw(); } } foreach (var TypeToCreate in PendingTypesToCreate) { TypeToCreate.CreateType(); } if (EntryPoint != null) { this.AssemblyBuilder.SetEntryPoint(EntryPoint); } if (SaveAssembly) { // Copy the runtime. var RuntimePath = typeof(CModuleAttribute).Assembly.Location; try { File.Copy(RuntimePath, OutFolder + "\\" + Path.GetFileName(RuntimePath), overwrite: true); } catch { } /* * if (EntryPoint != null) * { * OutputName = Path.GetFileNameWithoutExtension(OutputName) + ".exe"; * } * else * { * OutputName = Path.GetFileNameWithoutExtension(OutputName) + ".dll"; * } */ #if false Console.WriteLine("Writting to {0}", OutputName); #endif //this.AssemblyBuilder.Save(OutputName, PortableExecutableKinds.Required32Bit, ImageFileMachine.I386); this.AssemblyBuilder.Save(OutputName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386); } }); }); }); #if false } catch (Exception Exception) { if (ThrowException) { throw (Exception); } while (Exception.InnerException != null) { Exception = Exception.InnerException; } Console.Error.WriteLine(""); Console.Error.WriteLine("LastPosition: {0}", LastPositionInfo); Console.Error.WriteLine("{0} : '{1}'", Exception.TargetSite, Exception.Message); if (Exception.StackTrace != null) { Console.Error.WriteLine("{0}", String.Join("\n", Exception.StackTrace.Split('\n').Take(4))); Console.Error.WriteLine(" ..."); } } #endif }