public void IncludeString(string value) { var label = $@"""{value}"""; if (LabelDefs.ContainsKey(label)) { return; } Compilation.ConstData.Add(ConstRef(typeof(string).Id(), this)); ConstDef(label).Label(label); Compilation.ConstData.Add(value.Length); Compilation.ConstData.AddRange(value.Select(c => (int)c)); }
public void PatchLabels() { foreach (var labelRef in LabelRefs) { if (labelRef.RemoveCall) { CurrentLabelAddress = labelRef.Value; while (Compilation.Opcodes[CurrentLabelAddress] == Opcode.PFX0) { EmitOpcodes(Opcode.NOP); } if (Compilation.Opcodes[CurrentLabelAddress] == Opcode.PSH && Compilation.Opcodes[CurrentLabelAddress + 1] == Opcode.JSR) { EmitOpcodes(Opcode.NOP, Opcode.NOP); } continue; } Debug.Assert(LabelDefs.ContainsKey(labelRef.Name)); var labelDef = LabelDefs[labelRef.Name]; var labelValue = labelDef.IsAddressSlot ? Config.AddrIdxToAddrSlot(labelDef.Value) : labelDef.Value; if (labelRef.IsAddressSlot) { CurrentLabelAddress = labelRef.Value; EmitValue(labelValue, Config.BitsPerMemoryUnit); } else { Debug.Assert(labelRef.Value >= Config.ConstStart && labelRef.Value < Config.ConstStart + Config.ConstSize); Compilation.ConstData[labelRef.Value - Config.ConstStart] = labelValue; } } }
public Compiler EmitLabelDef(string label, Node owner = null, bool isMethod = false) { LabelDefs.Add(new Label(label, owner, CurrentAddrIdx, true)); return(this); }
public Compiler ConstDef(string name) => this.Assert(CurrentConstAddr > 0).With(c => LabelDefs.Add(new Label(name, null, CurrentConstAddr)));
public void Compile() { ProcessAssemblies(); Global.Compiler = this; Global.Config = Config; Include(GetClass(typeof(string))); Include(GetClass(typeof(int))); Include(GetClass(typeof(MethodMetadata))); Include(GetClass(typeof(MethodHandlerData))); Include(Main); EmitSource("Initialising stack and frame", "Startup"); Emit(Config.StackStart, Opcode.PSH, Opcode.POX); Emit(Config.StackStart + Config.StackSize - 1, Opcode.PSH, Opcode.POY); EmitSource("Initialising heap"); Emit(new Label(HeapInitialise, this), Opcode.PSH, Opcode.JSR); EmitSource("Calling static constructors"); Emit(new Label(CallCctors, this), Opcode.PSH, Opcode.JSR); EmitSource("Calling main"); Emit(new Label(Main, this), Opcode.PSH, Opcode.JSR); EmitSource("Break"); Emit(Break.InlineAction); EmitMethodData("Startup", "Startup.Startup", "Startup", null, new ArgData[0], new ArgData[0]); for (var i = 0; i < IncludedNodes.Count; i++) { IncludedNodes[i].GenerateExecutable(); } if (IncludedNodes.Contains(Newobj)) { HeapInitialise.GenerateExecutable(); } else { LabelRefs.Single(lr => lr.Name == HeapInitialise.Id).RemoveCall = true; } if (IncludedNodes.OfType <Method>().Any(m => m.Name == ".cctor")) { CallCctors.GenerateExecutable(); } else { LabelRefs.Single(lr => lr.Name == CallCctors.Id).RemoveCall = true; } Config.ExecutableSize = (Compilation.Opcodes.Count + Config.SlotsPerMemoryUnit - 1) / Config.SlotsPerMemoryUnit; Config.ConstStart = Config.ExecutableStart + Config.ExecutableSize; foreach (var node in IncludedNodes) { node.GenerateConstData(); } Config.MethodMetadata = CurrentConstAddr; Compilation.ConstData.Add(IncludedNodes.OfType <Method>().Count()); foreach (var node in IncludedNodes.OfType <Method>()) { node.GenerateMethodMetadata(); } Debug.Assert(CurrentConstAddr - Config.MethodMetadata == 1 + IncludedNodes.OfType <Method>().Count() * GetClass(typeof(MethodMetadata)).Elements.Count); Config.ConstSize = Compilation.ConstData.Count; Config.StaticSize = Compilation.StaticDataCount; LabelDefs.Add(new Label("Config.StaticSize", this, Config.StaticSize)); LabelDefs.Add(new Label("Config.MethodMetadata", this, Config.MethodMetadata)); PatchLabels(); Compilation.SetAddressInfo(); if (!string.IsNullOrEmpty(MifFileName)) { Compilation.WriteMif(MifFileName); } }