Click here to Skip to main content
15,885,309 members
Articles / Programming Languages / ASM

Bird Programming Language: Part 3

Rate me:
Please Sign up or sign in to vote.
4.88/5 (5 votes)
1 Jan 2013GPL35 min read 29.8K   282   14  
A new general purpose language that aims to be fast, high level and simple to use.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Bird
{
	public abstract class CondBranch
	{
	}

	public class JumpCodeBranch : CondBranch
	{
		public int Label;

		public JumpCodeBranch(int Label)
		{
			this.Label = Label;
		}
	}

	public class CodeCondBranch : CondBranch
	{
		public Action<CodeGenerator> GetCode;

		public CodeCondBranch(Action<CodeGenerator> GetCode)
		{
			this.GetCode = GetCode;
		}
	}

	public abstract class Instruction
	{
		public bool Skip = false;
	}

	public class LabelInstruction : Instruction
	{
		public int Label;
		public string Name;

		public LabelInstruction(int Label, string Name = null)
		{
			this.Label = Label;
			this.Name = Name;
		}

		public string LabelName
		{
			get { return Name == null ? "_" + Label : Name;	}
		}
	}

	public class JumpInstruction : Instruction
	{
		public int Label;
		public string Name;

		public JumpInstruction(int Label, string Name = null)
		{
			this.Label = Label;
			this.Name = Name;
		}

		public string LabelName
		{
			get { return Name == null ? "_" + Label : Name; }
		}
	}

	public sealed class ReplaceableJumpInstruction : JumpInstruction
	{
		public ReplaceableJumpInstruction(int Label)
			: base(Label)
		{
		}
	}

	public class StrInstruction : Instruction
	{
		public string Instruction;

		public StrInstruction(string Instruction)
		{
			this.Instruction = Instruction;
		}
	}

	public class InstructionContainer
	{
		public List<Instruction> Instructions = new List<Instruction>();
		public Dictionary<int, int> LabelPositions;

		public InstructionContainer()
		{
		}

		public void Add(Instruction Instruction)
		{
			if (Instruction is LabelInstruction)
			{
				var LblIns = Instruction as LabelInstruction;
				if (LabelPositions == null) LabelPositions = new Dictionary<int, int>();
				LabelPositions.Add(LblIns.Label, Instructions.Count);
			}

			Instructions.Add(Instruction);
		}

		public void Add(InstructionContainer InsContainer)
		{
			var Count = Instructions.Count;
			Instructions.AddRange(InsContainer.Instructions);

			if (InsContainer.LabelPositions != null)
			{
				foreach (var e in InsContainer.LabelPositions)
					LabelPositions.Add(e.Key, e.Value + Count);
			}
		}

		public void Add(string Str)
		{
			if (Str.Trim() == "mov dword[ebp - 12], _GetInt") { ; }
			Instructions.Add(new StrInstruction(Str));
		}

		public void Jump(int Label)
		{
			if (Label < 0) throw new ArgumentException(null, "Label");
			Instructions.Add(new ReplaceableJumpInstruction(Label));
		}

		public void Jump(string Label)
		{
			Instructions.Add(new JumpInstruction(-1, Label));
		}

		public void Label(string Label)
		{
			Instructions.Add(new LabelInstruction(-1, Label));
		}

		public void Label(int Label)
		{
			if (LabelPositions == null) LabelPositions = new Dictionary<int, int>();
			LabelPositions.Add(Label, Instructions.Count);

			var Ins = new LabelInstruction(Label);
			Instructions.Add(Ins);
		}

		public void Reset()
		{
			Instructions = new List<Instruction>();
			LabelPositions = new Dictionary<int, int>();
		}

		public void Insert(int Index, InstructionContainer InsContainer)
		{
			var P = InsContainer.Instructions.Count - 1;
			if (LabelPositions != null)
			{
				foreach (var e in LabelPositions.Keys.ToArray())
					if (LabelPositions[e] >= Index) LabelPositions[e] += P;
			}

			Instructions.InsertRange(Index, InsContainer.Instructions);
			if (InsContainer.LabelPositions != null)
			{
				foreach (var e in InsContainer.LabelPositions)
					LabelPositions.Add(e.Key, e.Value + Index);
			}
		}

		public int JumpsTo(int Label)
		{
			var InsIndex = LabelPositions[Label];
			for (var i = InsIndex; i < Instructions.Count; i++)
			{
				var Ins = Instructions[i];
				if (Ins is JumpInstruction)
				{
					var JumpIns = Ins as JumpInstruction;
					return JumpsTo(JumpIns.Label);
				}
				else if (Ins is LabelInstruction)
				{
					var LabelIns = Ins as LabelInstruction;
					Label = LabelIns.Label;
					continue;
				}

				break;
			}

			return Label;
		}

		public string EncodeToText(InstructionEncoder Encoder)
		{
			var StrBuilder = new StringBuilder();
			for (var i = 0; i < Instructions.Count; i++)
			{
				var Ins = Instructions[i];
				if (!Ins.Skip) 
					StrBuilder.Append(Encoder.EncodeToText(Ins));
			}

			return StrBuilder.ToString();
		}
	}

	public abstract class InstructionEncoder
	{
		public abstract string EncodeToText(Instruction Instruction);
	}

	public abstract class CodeGenerator
	{
		public CompilerState State;
		public IdContainer Container;

		public InstructionContainer InsContainer;
		public Dictionary<int, InstructionContainer> ReplaceJumps;

		public abstract void EmitExpression(ExpressionNode Node);
		public abstract void EmitCondition(ExpressionNode Node, CondBranch Then, CondBranch Else, int NextLabel = -1);
		public abstract void EmitCondition(ExpressionNode Node, int Then, int Else, bool ElseAfterCondition);

		public abstract void Align(int Align);
		public abstract void DeclareFile(string FileName);
		public abstract void DeclareLabelPtr(string Label);
		public abstract void DeclareLabelPtr(int Label);
		public abstract void DeclareUnknownBytes(int Count);
		public abstract void DeclareZeroBytes(int Count);
		public abstract void Declare(Identifier Type, ConstValue Data);
		public abstract void Store(string String, bool WideString = true, bool ZeroTerminated = true);

		public CodeGenerator(CompilerState State)
		{
			this.State = State;
			this.InsContainer = new InstructionContainer();
		}

		public void DeclareNull()
		{
			DeclareZeroBytes(State.Arch.RegSize);
		}

		public void Declare(ConstExpressionNode Value)
		{
			Declare(Value.Type.RealId as Type, Value.Value);
		}

		public void Declare(bool Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Boolean, new BooleanValue(Value));
		}

		public void Declare(string Value)
		{
			Declare(Container.GlobalContainer.CommonIds.String, new StringValue(Value));
		}

		public void Declare(float Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Single, new DoubleValue(Value));
		}

		public void Declare(double Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Double, new DoubleValue(Value));
		}

		public void Declare(long Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Int64, new IntegerValue(Value));
		}

		public void Declare(ulong Value)
		{
			Declare(Container.GlobalContainer.CommonIds.UInt64, new IntegerValue(Value));
		}

		public void Declare(int Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Int32, new IntegerValue(Value));
		}

		public void Declare(uint Value)
		{
			Declare(Container.GlobalContainer.CommonIds.UInt32, new IntegerValue(Value));
		}

		public void Declare(short Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Int32, new IntegerValue(Value));
		}

		public void Declare(ushort Value)
		{
			Declare(Container.GlobalContainer.CommonIds.UInt16, new IntegerValue(Value));
		}

		public void Declare(sbyte Value)
		{
			Declare(Container.GlobalContainer.CommonIds.SByte, new IntegerValue(Value));
		}

		public void Declare(byte Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Byte, new IntegerValue(Value));
		}

		public InstructionContainer ExecuteOnTempInsContainer(Action Action)
		{
			var InsContainer = new InstructionContainer();
			var OldInsContainer = this.InsContainer;
			this.InsContainer = InsContainer;

			Action();
			this.InsContainer = OldInsContainer;
			return InsContainer;
		}

		public InstructionContainer SetJumpReplacing(int Label, Action Action)
		{
			var InsContainer = ExecuteOnTempInsContainer(Action);
			SetJumpReplacing(Label, InsContainer);
			return InsContainer;
		}

		public void SetJumpReplacing(int Label, InstructionContainer InsContainer)
		{
			if (ReplaceJumps == null) ReplaceJumps = new Dictionary<int, InstructionContainer>();
			ReplaceJumps.Add(Label, InsContainer);
		}

		public virtual void SkipUnnecessaryJumps()
		{
			for (var i = 0; i < InsContainer.Instructions.Count; i++)
				InsContainer.Instructions[i].Skip = false;

			for (var i = 0; i < InsContainer.Instructions.Count; i++)
			{
				var JumpIns = InsContainer.Instructions[i] as JumpInstruction;
				if (JumpIns != null && !JumpIns.Skip)
				{
					var SkipInstructions = JumpIns is ReplaceableJumpInstruction;
					JumpIns.Label = InsContainer.JumpsTo(JumpIns.Label);

					for (var SkipPos = i + 1; SkipPos < InsContainer.Instructions.Count; SkipPos++)
					{
						var SIns = InsContainer.Instructions[SkipPos];
						if (SIns is LabelInstruction)
						{
							var SLabelIns = SIns as LabelInstruction;
							if (SLabelIns.Label == JumpIns.Label)
							{
								JumpIns.Skip = true;
								break;
							}
						}
						else if (SIns is JumpInstruction)
						{
							if (SkipInstructions) SIns.Skip = true;
							if (SIns is ReplaceableJumpInstruction && !SkipInstructions)
								break;
						}
						else
						{
							break;
						}
					}
				}
			}
		}

		public virtual void SkipUnnecessaryLabels()
		{
			var FS = Container.FunctionScope;
			for (var i = 0; i < InsContainer.Instructions.Count; i++)
			{
				var Ins = InsContainer.Instructions[i] as LabelInstruction;
				if (Ins != null && !FS.NeverSkippedLabels.Contains(Ins.Label))
					Ins.Skip = true;
			}

			for (var i = 0; i < InsContainer.Instructions.Count; i++)
			{
				var JumpIns = InsContainer.Instructions[i] as JumpInstruction;
				if (JumpIns != null && !JumpIns.Skip)
				{
					var JumpsTo = InsContainer.LabelPositions[JumpIns.Label];
					InsContainer.Instructions[JumpsTo].Skip = false;
				}
			}
		}

		public virtual void ProcessJumps()
		{
			SkipUnnecessaryJumps();

			if (ReplaceJumps != null)
			{
				var Instructions = InsContainer.Instructions;
				var Count = 0;
				Reset();

				for (var i = 0; i < Instructions.Count; i++)
				{
					var Ins = Instructions[i];
					if (!Ins.Skip)
					{
						var JIns = Ins as ReplaceableJumpInstruction;
						if (JIns != null && ReplaceJumps.ContainsKey(JIns.Label))
						{
							InsContainer.Add(ReplaceJumps[JIns.Label]);
							Count++;
							continue;
						}

						InsContainer.Add(Ins);
					}
				}

				if (Count > 0) ProcessJumps();
			}
		}

		public virtual void Optimize()
		{
			ProcessJumps();
			SkipUnnecessaryLabels();
		}

		public void Reset()
		{
			InsContainer.Reset();
		}
	}

	public interface IArchitecture
	{
		int RegSize { get; }
		int MaxStructPow2Size { get; }

		bool ProcessIdentifier(Identifier Id);
		bool ProcessFunction(Function Func);
		bool CreateAssembly(Function Func);
		void GetAssembly(CodeGenerator CG, Function Function);
		bool Compile(CompilerState State, CodeFile[] CodeFiles);


		bool IsSimpleCompareNode(ExpressionNode Node);
		CondBranch[] GetBranches(GlobalContainer Global, Command Then,
			Command Else, ref ExpressionNode Condition);
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions