Example #1
0
        private List <IMOperation> GenerateStringConcat(IMGeneratorEnv env, IMOperand target, IMOperand operand1, IMOperand operand2)
        {
            var result = new List <IMOperation>(20);

            var op1LengthLocation = IMOperand.Reference(DataType.U64, operand1);
            var op2LengthLocation = IMOperand.Reference(DataType.U64, operand2);

            //Calculate new string length
            var lengthLocation = env.NewTempLocal(DataType.U64);

            result.Add(IMOperation.Mov(lengthLocation, op1LengthLocation));
            result.Add(IMOperation.Add(lengthLocation, lengthLocation, op2LengthLocation));

            //Calculate new string byte size
            var byteSizeLocation = env.NewTempLocal(DataType.U64);

            result.Add(IMOperation.Mov(byteSizeLocation, lengthLocation));
            result.Add(IMOperation.Add(lengthLocation, lengthLocation, IMOperand.Immediate(DataType.U64, 9L)));

            //Reserve new memory on stack, which is freed automatically
            result.Add(IMOperation.SAloc(target, byteSizeLocation));

            //Copy target address
            var targetAddressLocation = env.NewTempLocal(target.DataType);

            result.Add(IMOperation.Mov(targetAddressLocation, target));

            //Write new string length to target
            result.Add(IMOperation.Mov(IMOperand.Reference(DataType.U64, targetAddressLocation), lengthLocation));

            //Move pointer to first char
            result.Add(IMOperation.Add(targetAddressLocation, targetAddressLocation, IMOperand.Immediate(DataType.U64, 8L)));

            var targetRefLocation = IMOperand.Reference(DataType.CHAR8, targetAddressLocation);

            //Get address of first char of operand1
            var sourceAddressLocation = env.NewTempLocal(target.DataType);

            result.Add(IMOperation.Mov(sourceAddressLocation, operand1));
            result.Add(IMOperation.Add(sourceAddressLocation, sourceAddressLocation, IMOperand.Immediate(DataType.U64, 8L)));

            var sourceRefLocation = IMOperand.Reference(DataType.CHAR8, sourceAddressLocation);

            var startLabel = env.NewLabelName();
            var endLabel   = env.NewLabelName();

            //Start label
            result.Add(IMOperation.Labl(startLabel));

            //Check if more chars to copy (string ends with 0 char)
            result.Add(IMOperation.JmpE(sourceRefLocation, IMOperand.Immediate(DataType.CHAR8, "\0"), endLabel));

            //Copy char
            result.Add(IMOperation.Mov(targetRefLocation, sourceRefLocation));

            //Inc target and source pointers
            result.Add(IMOperation.Add(targetAddressLocation, targetAddressLocation, IMOperand.Immediate(DataType.U64, 1L)));
            result.Add(IMOperation.Add(sourceAddressLocation, sourceAddressLocation, IMOperand.Immediate(DataType.U64, 1L)));

            //Next iteration
            result.Add(IMOperation.Jmp(startLabel));
            result.Add(IMOperation.Labl(endLabel));

            //Get address of first char of operand2
            result.Add(IMOperation.Mov(sourceAddressLocation, operand2));
            result.Add(IMOperation.Add(sourceAddressLocation, sourceAddressLocation, IMOperand.Immediate(DataType.U64, 8L)));

            startLabel = env.NewLabelName();
            endLabel   = env.NewLabelName();

            //Start label
            result.Add(IMOperation.Labl(startLabel));

            //Check if more chars to copy (string ends with 0 char)
            result.Add(IMOperation.JmpE(sourceRefLocation, IMOperand.Immediate(DataType.CHAR8, "\0"), endLabel));

            //Copy char
            result.Add(IMOperation.Mov(targetRefLocation, sourceRefLocation));

            //Inc target and source pointers
            result.Add(IMOperation.Add(targetAddressLocation, targetAddressLocation, IMOperand.Immediate(DataType.U64, 1L)));
            result.Add(IMOperation.Add(sourceAddressLocation, sourceAddressLocation, IMOperand.Immediate(DataType.U64, 1L)));

            //Next iteration
            result.Add(IMOperation.Jmp(startLabel));
            result.Add(IMOperation.Labl(endLabel));

            //Terminating 0
            result.Add(IMOperation.Mov(targetRefLocation, IMOperand.Immediate(DataType.U8, (byte)0)));

            return(result);
        }