public List <IMOperation> Generate(IMOperand target, IMOperand operand) { if (operand.DataType.Kind == DataTypeKind.ARRAY || operand.DataType.Kind == DataTypeKind.STRING8) { //Array already is a pointer, so directly use it //Add 8 bytes to array pointer so it points to first value, not to the length var result = new List <IMOperation>(2) { IMOperation.Mov(target, operand), IMOperation.Add(target, target, IMOperand.Immediate(DataType.U64, 8L)) }; return(result); } return(IMOperation.Lea(target, operand).AsList); }
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); }
/// <summary> /// Static stack allocation with size known at compile time. Will be allocated statically in the function prolog. /// </summary> /// <param name="target">The target.</param> /// <param name="numBytes">The number of bytes to allocate.</param> /// <returns></returns> public static IMOperation SAloc(IMOperand target, long numBytes) { return(new IMOperation(IMInstruction.SALOC, target, IMOperand.Immediate(DataType.U64, numBytes))); }