Difference between revisions of "WebAssembly/Internals"

From Lazarus wiki
Jump to navigationJump to search
Line 60: Line 60:
 
return
 
return
 
)
 
)
 
+
The code generation of '''cifnode''' is overridden.
 
</source>
 
</source>
  

Revision as of 18:14, 9 September 2019

Code Branching/Flow Control

todo: rewrite to the better explanation

WebAssembly doesn't allow direct jumps to (address/label)/or jump by offset. It only allows to jump "out-of" a code block, where the code block would be identified by a label. I.e. beginning of the loop label (for continue) or end of the loop label (for break). Loop itself is a single code block, known as "loop" in WebAssembly ).

FPC basic implementation is based of the ability of conditional jump instructions to a specified label. For that reason, the default implementation of TCGIfNode doesn't apply. Also, not every conditional jump instructions can have a label assign to it. Only instructions that jump out of the block are should use labels. Other, simply rely on the fact, that the next instruction IS the point they needs to be.

IF-block

Wasm IF do return a value (one of the basic WebAsm types). Pascal IF-statement does not return a value.

Thus the feature of value returning is not used (todo: but should be).

A dummy 0 value is pushed on the stack. IF is hard-coded to return i32 at all times.


According to the official documentation, IF always comes with "ELSE" block. However, some earlier versions do allow IF without an else statement. (which is also allowed in Binary specification of WASM). Such IF comes without any resulting type, and the execution of IF should leave stack unmodified in the end.

At this time "ELSE" branch is always generated for any IF statement. However, if there's no actual ELSE code (in pascal), a single "nop" instruction and a dummy result value produced.

function cmp(a,b: integer): Integer; 
begin
  if a > b then 
    cmp := 1
  else 
    cmp := 0;
end;

turns into:

(func $cmp
	(param	i32)
	(param	i32)
	(result	i32)
	(local	i32)	;; Temp 2,1 allocated
	(local	i32)	;; Temp 3,1 allocated
;; [3] begin
;; [4] if a > b then
	get_local	0
	set_local	3
	get_local	3
	get_local	1
	i32.gt_s
	if (result i32)  ;; hard-coded i32 type of IF result
;; [5] cmp := 1
	i32.const	1
	set_local	2
	i32.const	0 ;; mandatory wasm-IF result 
	else
;; [7] cmp := 0;
	i32.const	0
	set_local	2
	i32.const	0  ;; mandatory wasm-IF result
	end
	drop            ;; dropping IF-result from the stack, as unused
;; [8] end;
	get_local	2
	return
)
The code generation of '''cifnode''' is overridden.

See Also