/// <summary> /// Store the accumulator into the value at the placeholder /// </summary> public abstract void Store(Placeholder location);
public abstract Placeholder CheckOverflow(Placeholder overflowException);
/// <summary> /// Load the accumulator with the value at the placeholder /// </summary> public abstract void Load(Placeholder location);
public abstract void Source(Placeholder placeholder, ILocation location, SourceMark mark);
public abstract void CallNative(Placeholder function, int argumentCount, bool stackFrame, bool trampoline);
protected void SetExternals(Placeholder allocator, Placeholder toucher, Placeholder disposer, Placeholder exit, Placeholder setup, Placeholder saveStackRoot) { this.allocator = allocator; this.toucher = toucher; this.disposer = disposer; this.exit = exit; this.setup = setup; this.saveStackRoot = saveStackRoot; }
public void WritePlaceholder(Placeholder target) { RegionPlaceholder placeholder = SetupPlaceholder(target); placeholders.Add(placeholder); }
/// <summary> /// Stores the Accumulator into a field of the top of the stack. /// </summary> /// <param name="touch">Touch function of the garbage collector.</param> /// <param name="slot">Field number of the slot in Accumulator</param> public abstract void StoreInFieldOfSlot(Placeholder touch, int slot);
/// <summary> /// Stores the literal object value in the accumulator /// </summary> /// <param name="type">Placeholder of the type of the value</param> /// <param name="value">Placeholder of the value</param> public abstract void SetValue(Placeholder type, Placeholder value);
/// <summary> /// Places the methodStruct as the type part of the Accumulator. /// The value part of the Accumulator is cleared. /// Only suited for static methods. /// </summary> /// <param name="methodStruct">Pointer placeholder to a method type struct.</param> public abstract void LoadMethodStruct(Placeholder methodStruct);
/// <summary> /// Generates code that calls the allocator with the desired size and the places the memory as the value part in the Accumulator /// the type part of the Accumulator is filled with the type pointer placeholder. /// </summary> /// <param name="allocator">Placeholder to the allocator implementation</param> /// <param name="size">Size in bytes to allocate</param> /// <param name="type">Placeholder to put in the type part of the new value in the Accumulator</param> public abstract void CallAllocator(Placeholder allocator, int size, Placeholder type);
/// <summary> /// Calls the method which start position was passed. /// Arguments were pushed left to right. /// </summary> /// <param name="function">location of the start of the function</param> public abstract Placeholder CallDirect(Placeholder function);
public void Source(Placeholder placeholder, ILocation location) { Source(placeholder, location, SourceMark.Normal); }
public abstract void WriteData(Placeholder location, long length, string token);
/// <summary> /// Jumps to the location stored in the placeholder. /// </summary> /// <param name="location"></param> public abstract void JumpBuildIn(Placeholder location);
/// <summary> /// Stores the literal object value in the accumulator /// </summary> /// <param name="type">Placeholder of the type of the value</param> /// <param name="value">Value of the value</param> public abstract void SetImmediateValue(Placeholder type, long value);
public abstract void AddCallTraceEntry(Placeholder retPointer, ILocation location, string definition, string method);
/// <summary> /// Does a normal stdcall to the pointer to function pointer, with the arguments in normal order ont he stack (not pluk order) /// </summary> /// <param name="indirectFunction">pointer to function pointer to call</param> /// <param name="arguments">array of arguments</param> public abstract void CallBuildIn(Placeholder indirectFunction, Placeholder[] arguments);
public abstract void WriteGlobalSymbol(string name, Placeholder location);
/// <summary> /// Overwrites the type part of the accumulator. /// Usefull for callspec conversions. /// </summary> /// <param name="type"></param> //TODO: change to put the literal/pointer in de data section public abstract void SetTypePart(Placeholder type);
internal LongToken(Stream stream, Placeholder location) { this.stream = stream; position = stream.Position; this.location = location; }
static int Main(string[] args) { try { List <string> types = new List <string>(); Set <string> paths = new Set <string>(); List <string> files = new List <string>(); Set <string> hiddenPaths = new Set <string>(); bool noDefaultPaths = false; bool path = false; bool noMoreFlags = false; bool showPathAndFiles = false; bool hiddenPath = false; bool breakOnStart = false; bool showUsedTypes = false; bool noEntryPoint = false; foreach (string s in args) { bool file = path || noMoreFlags; if (!file) { if (s == "-m:l64") { if (Windows_x86 || Linux_x86 || Windows_x86_64 || Linux_x86_64) { throw new Exception("Only one platform can be used at a time."); } linux_x86_64 = true; } else if (s == "-m:l32") { if (Windows_x86 || Linux_x86 || Windows_x86_64 || Linux_x86_64) { throw new Exception("Only one platform can be used at a time."); } linux_x86 = true; } else if (s == "-m:w64") { if (Windows_x86 || Linux_x86 || Windows_x86_64 || Linux_x86_64) { throw new Exception("Only one platform can be used at a time."); } windows_x86_64 = true; } else if (s == "-m:w32") { if (Windows_x86 || Linux_x86 || Windows_x86_64 || Linux_x86_64) { throw new Exception("Only one platform can be used at a time."); } windows_x86 = true; } else if (s == "-p") { path = true; } else if (s == "-ndp") { noDefaultPaths = true; } else if (s == "-x:v") { Console.WriteLine("Version " + version); } else if (s == "-x:ns") { stackTrace = false; } else if (s == "-x:s") { stackTrace = true; } else if (s == "-a:v") { allowUnreadAndUnusedVariablesFieldsAndExpressions = true; } else if (s == "-x:nf") { suppressPathInErrors = true; } else if (s == "-x:p") { showPathAndFiles = true; } else if (s == "-x:f") { writeFileNameOnRead = true; } else if (s == "-x:fnc") { caseSensitive = false; } else if (s == "-x:fc") { caseSensitive = true; } else if (s == "-x:b") { breakOnStart = true; } else if (s == "-x:t") { showUsedTypes = true; } else if (s == "-x:e") { noEntryPoint = true; } else if (s == "-p:h") { path = true; hiddenPath = true; } else if (s == "--") { noMoreFlags = true; } else { file = true; } } if (file) { if (path) { if (hiddenPath) { hiddenPaths.Put(Path.GetFullPath(s)); } else { paths.Put(Path.GetFullPath(s)); } } else if (s.Contains(".pluk")) { files.Add(Path.GetFullPath(s)); } else { types.Add(s); } path = false; hiddenPath = false; } } if (!noDefaultPaths) { string env_pluk_source = Environment.GetEnvironmentVariable("PLUK_SOURCES"); if (!string.IsNullOrEmpty(env_pluk_source)) { paths.Put(Path.GetFullPath(env_pluk_source)); } paths.Put(Path.GetFullPath(".")); foreach (string p in hiddenPaths) { paths.Put(p); } } if (showPathAndFiles) { foreach (string type in types) { Console.WriteLine("type: " + type); } foreach (string file in files) { Console.WriteLine("file: " + file); } foreach (string vpath in paths) { Console.WriteLine("path: " + vpath); } } if (!(Windows_x86 || Linux_x86 || Windows_x86_64 || Linux_x86_64)) { if (Environment.OSVersion.Platform == PlatformID.Unix) { if (IntPtr.Size == 8) { linux_x86_64 = true; } else if (IntPtr.Size == 4) { linux_x86 = true; } else { throw new ArgumentOutOfRangeException("unsupported pointer width: " + IntPtr.Size); } } else { // if (IntPtr.Size == 8) // windows_x86_64 = true; // else if (IntPtr.Size == 4) windows_x86 = true; // else // throw new ArgumentOutOfRangeException("unsupported pointer width: " + IntPtr.Size); } } if ((types.Count == 0) && (files.Count == 0)) { throw new ArgumentException(string.Format(Resource.Culture, Resource.CompilerUsage, AppDomain.CurrentDomain.FriendlyName)); } types.Add("pluk.base.String"); types.Add("pluk.base.Int"); types.Add("pluk.base.Float"); types.Add("pluk.base.Bool"); types.Add("pluk.base.StaticString"); types.Add("pluk.base.Object"); types.Add("pluk.base.Application"); types.Add("pluk.base.OverflowException"); types.Add("pluk.base.BoundsException"); if (paths.Count == 0) { paths.Add(Path.GetFullPath(".")); } Generator generator = null; if (Linux_x86_64) { generator = new Compiler.Binary.LinuxELF64X86_64.Generator(paths, !CaseSensitiveFileSystem); } if (Linux_x86) { generator = new Compiler.Binary.LinuxELF32X86.Generator(paths, !CaseSensitiveFileSystem); } if (Windows_x86) { generator = new Compiler.Binary.WinPE32X86.Generator(paths, !CaseSensitiveFileSystem); } Require.Assigned(generator); try { string baseClass = null; if (files.Count == 0) { baseClass = types[0]; } foreach (string file in files) { string typename = generator.Resolver.ParseFile(file); if (baseClass == null) { baseClass = typename; } } generator.SetModuleName(baseClass); foreach (string type in types) { TypeName tn = new TypeName(new Identifier(new NowhereLocation(), type)); tn.SetHasNamespace(); generator.Resolver.ResolveType(new NowhereLocation(), tn); } TypeName baseClassType = new TypeName(new Identifier(new NowhereLocation(), baseClass)); baseClassType.SetHasNamespace(); if (noEntryPoint) { ResolveBaseTypes(generator); generator.Resolver.ResolveEverything(generator); generator.Resolver.PrepareEverything(generator); generator.Resolver.GenerateEverything(generator); } else { ResolveBaseTypes(generator); generator.Resolver.ResolveEverything(generator); Definition t = generator.Resolver.ResolveDefinitionType(new NowhereLocation(), baseClassType).Definition; generator.Resolver.PrepareEverything(generator); generator.Resolver.GenerateEverything(generator); CheckHelper.SetupExceptionHandlers(generator); DefinitionTypeReference applicationType = generator.Resolver.ResolveDefinitionType(new NowhereLocation(), new TypeName(new Identifier(new NowhereLocation(), "pluk.base.Application"))); if (!t.Supports(applicationType)) { throw new CompilerException(t, string.Format(Resource.Culture, Resource.ClassHasNoMain, baseClass)); } generator.AllocateAssembler(); Assembler g = generator.Assembler; if (breakOnStart) { g.Break(); } g.StackRoot(); g.CallNative(generator.SaveStackRoot, 1, false, false); g.StartFunction(); // setup basic types in pluk_base.dll SetupBaseTypes(generator); //reset floating point mask generator.Assembler.SetupFpu(); generator.Resolver.CallStaticInitializers(generator); //Instance program object and call the main method g.LoadMethodStruct(t.FindConstructor(new NowhereLocation(), new FunctionTypeReference(new NowhereLocation(), t.TypeReference, new List <TypeReference>()), applicationType.Definition).RuntimeStruct); g.PushValue(); Placeholder retSite = g.CallFromStack(0); generator.AddCallTraceEntry(retSite, new NowhereLocation(), "", "entrypoint"); Method m = t.FindMethod(new Identifier(new NowhereLocation(), "MainIndirect"), false, null, applicationType.Definition, true); g.FetchMethod(t.GetMethodOffset(new NowhereLocation(), m, applicationType.Definition)); g.PushValue(); retSite = g.CallFromStack(0); generator.AddCallTraceEntry(retSite, new NowhereLocation(), "", "entrypoint"); // todo, provide argument g.Empty(); g.PushValue(); g.PopNativeArgument(); g.CallNative(generator.Exit, 2, false, false); g.StopFunction(); generator.Symbols.WriteCode(generator.Assembler.Region.BaseLocation, generator.Assembler.Region.Length, "entryPoint:" + baseClass + ".Main"); generator.Symbols.WriteCode(generator.Assembler.Region.BaseLocation, generator.Assembler.Region.Length, "_start"); generator.Symbols.WriteCode(generator.Assembler.Region.BaseLocation, generator.Assembler.Region.Length, "main"); generator.WriteToFile(g.Region); } if (showUsedTypes) { foreach (Definition def in generator.Definitions) { Console.WriteLine("Definition: " + def.Name.DataModifierLess); } } } finally { generator.Dispose(); } } catch (CompilerException ce) { if (stackTrace) { Console.Error.WriteLine(ce.ToString()); } else if (suppressPathInErrors) { Console.Error.WriteLine(ce.Error); } else { Console.Error.WriteLine(ce.ErrorMessage); } return(1); } catch (Exception e) { if (stackTrace) { Console.Error.WriteLine(e.ToString()); } else { Console.Error.WriteLine(e.Message); } return(255); } return(0); }