Exemple #1
0
        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));
        }
Exemple #2
0
        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;
                }
            }
        }
Exemple #3
0
 public Compiler EmitLabelDef(string label, Node owner = null, bool isMethod = false)
 {
     LabelDefs.Add(new Label(label, owner, CurrentAddrIdx, true));
     return(this);
 }
Exemple #4
0
 public Compiler ConstDef(string name)
 => this.Assert(CurrentConstAddr > 0).With(c => LabelDefs.Add(new Label(name, null, CurrentConstAddr)));
Exemple #5
0
        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);
            }
        }