Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra PC increment in JMP instruction #490

Open
2 tasks
KSpaceer opened this issue May 13, 2024 · 0 comments
Open
2 tasks

Extra PC increment in JMP instruction #490

KSpaceer opened this issue May 13, 2024 · 0 comments

Comments

@KSpaceer
Copy link

You must post issues only here. Questions, ideas must be posted in discussions.

  • GopherLua is a Lua5.1 implementation. You should be familiar with Lua programming language. Have you read Lua 5.1 reference manual carefully?
  • GopherLua is a Lua5.1 implementation. In Lua, to keep it simple, it is more important to remove functionalities rather than to add functionalities unlike other languages . If you are going to introduce some new cool functionalities into the GopherLua code base and the functionalities can be implemented by existing APIs, It should be implemented as a library.

Please answer the following before submitting your issue:

  1. What version of GopherLua are you using? : v1.1.1
  2. What version of Go are you using? : 1.22.2
  3. What operating system and processor architecture are you using? : Ubuntu 22.04 x86_64
  4. What did you do? :
function greaterThan(a, b)
	return a > b
end

function lessThan(a, b)
	return a < b
end

function betweenViaOperators(val, a, b)
  local result = true
  result = result and (val > a and val < b)
  return result
end

function betweenViaFunctions(val, a, b)
  local result = true
  result = result and (greaterThan(val, a) and lessThan(val, b))
  return result
end

print(betweenViaOperators(2, 3, 5))
print(betweenViaFunctions(2, 3, 5))
  1. What did you expect to see? :
false
false
  1. What did you see instead? :
false
true

It seems to happen because of some optimizations or something like that. In case of comparison via functions we have following bytecode for the betweenViaFunctions function:

; function [3] definition (level 2)
          ; 0 upvalues, 3 params, 7 stacks
          .local val ; 0
          .local a ; 1
          .local b ; 2
          .local result ; 3
          .const greaterThan ; 0
          .const lessThan ; 1
        
          [001] LOADBOOL      |  3, 1, 0; R(3) := (Bool)1; if (0) pc++ (line:17)
          [002] TEST      |  3, 3, 0; if not (R(3) <=> 0) then pc++ (line:18)
          [003] JMP      |  0, 11; pc+=11 (line:18)
          [004] GETGLOBAL      |  4, 0; R(4) := Gbl[Kst(0)] (line:18)
          [005] MOVEN      |  5, 0, 1; R(5) := R(0); followed by 1 MOVE ops (line:18)
          [006] MOVE      |  6, 1, 0; R(6) := R(1) (line:18)
          [007] CALL      |  4, 3, 2; R(4) ... R(4+2-2) := R(4)(R(4+1) ... R(4+3-1)) (line:18)
          [008] TEST      |  4, 0, 0; if not (R(4) <=> 0) then pc++ (line:18)
          [009] JMP      |  0, 5; pc+=5 (line:18)
          [010] GETGLOBAL      |  4, 1; R(4) := Gbl[Kst(1)] (line:18)
          [011] MOVEN      |  5, 0, 1; R(5) := R(0); followed by 1 MOVE ops (line:18)
          [012] MOVE      |  6, 2, 0; R(6) := R(2) (line:18)
          [013] CALL      |  4, 3, 2; R(4) ... R(4+2-2) := R(4)(R(4+1) ... R(4+3-1)) (line:18)
          [014] MOVE      |  3, 4, 0; R(3) := R(4) (line:18)
          [015] RETURN      |  3, 2, 0; return R(3) ... R(3+2-2) (line:19)
          [016] RETURN      |  0, 1, 0; return R(0) ... R(0+1-2) (line:20)
          ; end of function

Please pay attention for the 003 and 009 JMP instructions: they go to the 014 MOVE instruction, which is responisble for the result variable assignment. When JMP instructions are executed, the program counter points to the MOVE instruction, and then in the main loop (vm.go:30) the PC increments. After this operation the PC points to the 015 RETURN, that leads to the returning of wrong value.

For comparsion, there is the betweenViaOperators bytecode:

; function [2] definition (level 2)
          ; 0 upvalues, 3 params, 4 stacks
          .local val ; 0
          .local a ; 1
          .local b ; 2
          .local result ; 3
        
          [001] LOADBOOL      |  3, 1, 0; R(3) := (Bool)1; if (0) pc++ (line:11)
          [002] TEST      |  3, 3, 0; if not (R(3) <=> 0) then pc++ (line:12)
          [003] JMP      |  0, 6; pc+=6 (line:12)
          [004] LT      |  0, 1, 0; if ((RK(1) <  RK(0)) ~= 0) then pc++ (line:12)
          [005] JMP      |  0, 2; pc+=2 (line:12)
          [006] LT      |  1, 0, 2; if ((RK(0) <  RK(2)) ~= 1) then pc++ (line:12)
          [007] JMP      |  0, 1; pc+=1 (line:12)
          [008] LOADBOOL      |  3, 0, 1; R(3) := (Bool)0; if (1) pc++ (line:12)
          [009] LOADBOOL      |  3, 1, 0; R(3) := (Bool)1; if (0) pc++ (line:12)
          [010] RETURN      |  3, 2, 0; return R(3) ... R(3+2-2) (line:13)
          [011] RETURN      |  0, 1, 0; return R(0) ... R(0+1-2) (line:14)
          ; end of function

We can see that JMP instructions will lead to the 009 LOADBOOL instruction (considering PC increment in the main loop), which is correct and leads to the true returning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant