Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit xprInterpreter;
- {
- Author: Jarl K. Holta
- License: GNU Lesser GPL (http://www.gnu.org/licenses/lgpl.html)
- }
- {$I header.inc}
- {$hints off}
- interface
- uses
- SysUtils, xprTypes, xprBytecode, xprErrors;
- type
- TStack64k = array [0..$FFFF] of record
- case Byte of
- 1: (b: Boolean;);
- 2: (f: Double;);
- 3: (i: Int64; );
- end;
- TConst64k = array [0..$FFFF] of TConstant;
- TInterpreter = record
- Bytecode: TByteCode;
- FProgram: Pointer;
- FStack: TStack64k;
- FConst: TConst64k;
- procedure Compile(BC: TBytecode);
- end;
- implementation
- uses
- Math;
- {$DEFINE COPY_CODE_RESULT :=
- if Op.Args[2].Typ in XprFloatTypes then
- begin
- if (Op.Args[0].Pos = EMemPos.mpUnalloc) and (Op.Args[1].Pos = EMemPos.mpUnalloc) then
- Result := GetCode(@f_stack_stack, @f_stack_const)
- else if (Op.Args[0].Pos = EMemPos.mpUnalloc) and (Op.Args[1].Pos = EMemPos.mpTable) then
- Result := GetCode(@f_stack_const, @f_const_stack)
- else if (Op.Args[0].Pos = EMemPos.mpTable) and (Op.Args[1].Pos = EMemPos.mpUnalloc) then
- Result := GetCode(@f_const_stack, @body);
- end else
- begin
- if (Op.Args[0].Pos = EMemPos.mpUnalloc) and (Op.Args[1].Pos = EMemPos.mpUnalloc) then
- Result := GetCode(@i_stack_stack, @i_stack_const)
- else if (Op.Args[0].Pos = EMemPos.mpUnalloc) and (Op.Args[1].Pos = EMemPos.mpTable) then
- Result := GetCode(@i_stack_const, @i_const_stack)
- else if (Op.Args[0].Pos = EMemPos.mpTable) and (Op.Args[1].Pos = EMemPos.mpUnalloc) then
- Result := GetCode(@i_const_stack, @f_stack_stack);
- end
- }
- {$DEFINE COPY_CODE_RESULT_ASGN :=
- if Op.Args[2].Typ in XprFloatTypes then
- begin
- if (Op.Args[1].Pos = EMemPos.mpUnalloc) then Result := GetCode(@f_stack_stack, @f_stack_const)
- else if (Op.Args[1].Pos = EMemPos.mpTable) then Result := GetCode(@f_stack_const, @i_stack_stack)
- end else
- begin
- if (Op.Args[1].Pos = EMemPos.mpUnalloc) then Result := GetCode(@i_stack_stack, @i_stack_const)
- else if (Op.Args[1].Pos = EMemPos.mpTable) then Result := GetCode(@i_stack_const, @body)
- end
- }
- function GetCode(start, stop: Pointer): TBytes;
- var sz: SizeInt;
- begin
- sz := PtrUInt(stop) - PtrUInt(start);
- SetLength(Result, sz);
- Move(start^, Result[0], sz);
- end;
- function Get_MUL_Code(var FStack: TStack64k; var FConst: TConst64k; const Op: TInstruction): TBytes;
- label i_stack_stack, i_stack_const, i_const_stack, f_stack_stack, f_stack_const, f_const_stack, body;
- begin
- goto body;
- i_stack_stack: FStack[Op.Args[2].Arg].i := FStack[Op.Args[0].Arg].i * FStack[Op.Args[1].Arg].i;
- i_stack_const: FStack[Op.Args[2].Arg].i := FStack[Op.Args[0].Arg].i * FConst[Op.Args[1].Arg].i;
- i_const_stack: FStack[Op.Args[2].Arg].i := FConst[Op.Args[0].Arg].i * FStack[Op.Args[1].Arg].i;
- f_stack_stack: FStack[Op.Args[2].Arg].f := FStack[Op.Args[0].Arg].f * FStack[Op.Args[1].Arg].f;
- f_stack_const: FStack[Op.Args[2].Arg].f := FStack[Op.Args[0].Arg].f * FConst[Op.Args[1].Arg].f;
- f_const_stack: FStack[Op.Args[2].Arg].f := FConst[Op.Args[0].Arg].f * FStack[Op.Args[1].Arg].f;
- body:
- COPY_CODE_RESULT;
- end;
- function Get_EQ_Code(var FStack: TStack64k; var FConst: TConst64k; const Op: TInstruction): TBytes;
- label i_stack_stack, i_stack_const, i_const_stack, f_stack_stack, f_stack_const, f_const_stack, body;
- begin
- goto body;
- i_stack_stack: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].i = FStack[Op.Args[1].Arg].i;
- i_stack_const: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].i = FConst[Op.Args[1].Arg].i;
- i_const_stack: FStack[Op.Args[2].Arg].b := FConst[Op.Args[0].Arg].i = FStack[Op.Args[1].Arg].i;
- f_stack_stack: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].f = FStack[Op.Args[1].Arg].f;
- f_stack_const: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].f = FConst[Op.Args[1].Arg].f;
- f_const_stack: FStack[Op.Args[2].Arg].b := FConst[Op.Args[0].Arg].f = FStack[Op.Args[1].Arg].f;
- body:
- COPY_CODE_RESULT;
- end;
- function Get_LTE_Code(var FStack: TStack64k; var FConst: TConst64k; const Op: TInstruction): TBytes;
- label i_stack_stack, i_stack_const, i_const_stack, f_stack_stack, f_stack_const, f_const_stack, body;
- begin
- goto body;
- i_stack_stack: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].i <= FStack[Op.Args[1].Arg].i;
- i_stack_const: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].i <= FConst[Op.Args[1].Arg].i;
- i_const_stack: FStack[Op.Args[2].Arg].b := FConst[Op.Args[0].Arg].i <= FStack[Op.Args[1].Arg].i;
- f_stack_stack: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].f <= FStack[Op.Args[1].Arg].f;
- f_stack_const: FStack[Op.Args[2].Arg].b := FStack[Op.Args[0].Arg].f <= FConst[Op.Args[1].Arg].f;
- f_const_stack: FStack[Op.Args[2].Arg].b := FConst[Op.Args[0].Arg].f <= FStack[Op.Args[1].Arg].f;
- body:
- COPY_CODE_RESULT;
- end;
- function Get_ASGN_Code(var FStack: TStack64k; var FConst: TConst64k; const Op: TInstruction): TBytes;
- label i_stack_stack, i_stack_const, f_stack_stack, f_stack_const, body;
- begin
- goto body;
- i_stack_stack: FStack[Op.Args[0].Arg].i := FStack[Op.Args[1].Arg].i;
- i_stack_const: FStack[Op.Args[0].Arg].i := FConst[Op.Args[1].Arg].i;
- f_stack_stack: FStack[Op.Args[0].Arg].f := FStack[Op.Args[1].Arg].f;
- f_stack_const: FStack[Op.Args[0].Arg].f := FConst[Op.Args[1].Arg].f;
- body:
- COPY_CODE_RESULT_ASGN;
- end;
- function Get_LADD_Code(var FStack: TStack64k; var FConst: TConst64k; const Op: TInstruction): TBytes;
- label i_stack_stack, i_stack_const, f_stack_stack, f_stack_const, body;
- begin
- goto body;
- i_stack_stack: FStack[Op.Args[0].Arg].i += FStack[Op.Args[1].Arg].i;
- i_stack_const: FStack[Op.Args[0].Arg].i += FConst[Op.Args[1].Arg].i;
- f_stack_stack: FStack[Op.Args[0].Arg].f += FStack[Op.Args[1].Arg].f;
- f_stack_const: FStack[Op.Args[0].Arg].f += FConst[Op.Args[1].Arg].f;
- body:
- COPY_CODE_RESULT_ASGN;
- end;
- function Get_LSUB_Code(var FStack: TStack64k; var FConst: TConst64k; const Op: TInstruction): TBytes;
- label i_stack_stack, i_stack_const, f_stack_stack, f_stack_const, body;
- begin
- goto body;
- i_stack_stack: FStack[Op.Args[0].Arg].i -= FStack[Op.Args[1].Arg].i;
- i_stack_const: FStack[Op.Args[0].Arg].i -= FConst[Op.Args[1].Arg].i;
- f_stack_stack: FStack[Op.Args[0].Arg].f -= FStack[Op.Args[1].Arg].f;
- f_stack_const: FStack[Op.Args[0].Arg].f -= FConst[Op.Args[1].Arg].f;
- body:
- COPY_CODE_RESULT_ASGN;
- end;
- procedure TInterpreter.Compile(BC: TByteCode): TByteCode;
- var
- i,j: Int32;
- jumps: array of record From, Goal:PtrUInt; machineGoal: PtrUInt; end;
- compiled, code: TBytes;
- jmp: record From, Goal:PtrUInt; machineGoal: PtrUInt; end;
- procedure AddJump(From, Goal: PtrUInt);
- begin
- SetLength(jumps, Length(jumps)+1);
- jumps[High(jumps)].From := From;
- jumps[High(jumps)].Goal := Goal;
- end;
- var
- raw: TBytes;
- begin
- Self.Bytecode := BC;
- Move(BC.Constants.Data[0], Self.FConst[0], (BC.Constants.High+1)*SizeOf(TConstant));
- FillByte(Self.FStack, $FFFF*SizeOf(Int64), 0);
- for i:=0 to bc.Code.High do
- begin
- if bc.Code.data[i].Code = bcRELJMP then AddJump(i, i+bc.Code.data[i].Args[0].Arg);
- if bc.Code.data[i].Code = bcJZ then AddJump(i, bc.Code.data[i].Args[1].Arg);
- if bc.Code.data[i].Code = bcJNZ then AddJump(i, bc.Code.data[i].Args[1].Arg);
- end;
- for i:=0 to bc.Code.High do
- begin
- // patch location
- for j:=0 to High(jumps) do
- begin
- if jumps[j].Goal = i then jumps[j].machineGoal := Length(Result);
- if jumps[j].From = i then jmp := jumps[i];
- end;
- if bc.Code.Data[i].Code in [bcJZ, bcRELJMP, RETURN] then
- begin
- // compiled code is moved to special opcode
- // Result.Append(Opcode(bcExecutableMem, pointer_to_exec_mem);
- // where pointer_to_exec_mem is VirtualAlloc from the current compiled snippet
- // reset "compiled"
- // Result.Append(bc.Code.Data[i]);
- end
- else
- begin
- case bc.Code.Data[i].Code of
- bcASGN: code := Get_ASGN_Code(Self.FStack, Self.FConst, bc.Code.data[i]);
- bcLADD: code := Get_LADD_Code(Self.FStack, Self.FConst, bc.Code.data[i]);
- bcLSUB: code := Get_LSUB_Code(Self.FStack, Self.FConst, bc.Code.data[i]);
- bcLTE: code := Get_LTE_Code(Self.FStack, Self.FConst, bc.Code.data[i]);
- bcEQ: code := Get_EQ_Code (Self.FStack, Self.FConst, bc.Code.data[i]);
- bcMUL: code := Get_MUL_Code(Self.FStack, Self.FConst, bc.Code.data[i]);
- end;
- //add code to the final compiled .. compiled.Extend(code)
- end;
- end;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement