Browse Source

+ WebAssembly inline assembler instruction parsing work in progress

Nikolay Nikolov 1 year ago
parent
commit
c6e715a54e
2 changed files with 289 additions and 6 deletions
  1. 14 0
      compiler/wasm32/rawasm.pas
  2. 275 6
      compiler/wasm32/rawasmtext.pas

+ 14 - 0
compiler/wasm32/rawasm.pas

@@ -35,9 +35,23 @@ unit rawasm;
       TWasmOperand=class(TOperand)
       TWasmOperand=class(TOperand)
       end;
       end;
 
 
+      { TWasmInstruction }
+
       TWasmInstruction=class(TInstruction)
       TWasmInstruction=class(TInstruction)
+        procedure AddParam(const id: string; typ: TWasmBasicType);
+        procedure AddResult(typ: TWasmBasicType);
       end;
       end;
 
 
   implementation
   implementation
 
 
+  { TWasmInstruction }
+
+    procedure TWasmInstruction.AddParam(const id: string; typ: TWasmBasicType);
+      begin
+      end;
+
+    procedure TWasmInstruction.AddResult(typ: TWasmBasicType);
+      begin
+      end;
+
 end.
 end.

+ 275 - 6
compiler/wasm32/rawasmtext.pas

@@ -35,13 +35,14 @@ Unit rawasmtext;
     type
     type
       tasmtoken = (
       tasmtoken = (
         AS_NONE,AS_LPAREN,AS_RPAREN,AS_ID,AS_END,AS_OPCODE,AS_INTNUM,
         AS_NONE,AS_LPAREN,AS_RPAREN,AS_ID,AS_END,AS_OPCODE,AS_INTNUM,
-        AS_REALNUM,AS_STRING
+        AS_REALNUM,AS_STRING,AS_PARAM,AS_RESULT,AS_THEN,AS_ELSE,AS_TYPE,AS_VALTYPE
       );
       );
       tasmkeyword = string[10];
       tasmkeyword = string[10];
 
 
     const
     const
       token2str : array[tasmtoken] of tasmkeyword=(
       token2str : array[tasmtoken] of tasmkeyword=(
-        '','(',')','identifier','end','opcode','integer','float','string');
+        '','(',')','identifier','end','opcode','integer','float','string',
+        'param','result','then','else','type','valtype');
 
 
     type
     type
 
 
@@ -49,6 +50,7 @@ Unit rawasmtext;
 
 
       twasmreader = class(tasmreader)
       twasmreader = class(tasmreader)
       private
       private
+        actwasmbasictype: TWasmBasicType;
         actasmpattern_origcase: string;
         actasmpattern_origcase: string;
         actasmtoken   : tasmtoken;
         actasmtoken   : tasmtoken;
         prevasmtoken  : tasmtoken;
         prevasmtoken  : tasmtoken;
@@ -56,6 +58,11 @@ Unit rawasmtext;
         procedure GetToken;
         procedure GetToken;
         function consume(t : tasmtoken):boolean;
         function consume(t : tasmtoken):boolean;
         function is_asmopcode(const s: string):boolean;
         function is_asmopcode(const s: string):boolean;
+        function is_valtype(const s: string):boolean;
+        procedure HandleInstruction;
+        procedure HandleFoldedInstruction;
+        procedure HandlePlainInstruction;
+        procedure HandleBlockInstruction;virtual;abstract;
       public
       public
         function Assemble: tlinkedlist;override;
         function Assemble: tlinkedlist;override;
       end;
       end;
@@ -185,10 +192,9 @@ Unit rawasmtext;
               actasmpattern_origcase:=actasmpattern;
               actasmpattern_origcase:=actasmpattern;
               if actasmpattern[1]='$' then
               if actasmpattern[1]='$' then
                 actasmtoken:=AS_ID
                 actasmtoken:=AS_ID
-              else if is_asmopcode(actasmpattern) then
-                begin
-                  exit;
-                end
+              else if is_asmopcode(actasmpattern) or
+                      is_valtype(actasmpattern) then
+                exit
               else if upper(actasmpattern) = 'END' then
               else if upper(actasmpattern) = 'END' then
                 begin
                 begin
                   uppervar(actasmpattern);
                   uppervar(actasmpattern);
@@ -447,6 +453,269 @@ Unit rawasmtext;
       end;
       end;
 
 
 
 
+    function twasmreader.is_valtype(const s: string): boolean;
+      begin
+        actwasmbasictype:=wbt_Unknown;
+        case s of
+          'i32':
+             actwasmbasictype:=wbt_i32;
+          'i64':
+             actwasmbasictype:=wbt_i64;
+          'f32':
+             actwasmbasictype:=wbt_f32;
+          'f64':
+             actwasmbasictype:=wbt_f64;
+          'funcref':
+             actwasmbasictype:=wbt_funcref;
+          'externref':
+             actwasmbasictype:=wbt_externref;
+          'v128':
+             actwasmbasictype:=wbt_v128;
+        end;
+        if actwasmbasictype<>wbt_Unknown then
+          begin
+            actasmtoken:=AS_VALTYPE;
+            is_valtype:=true;
+          end
+        else
+          is_valtype:=false;
+      end;
+
+
+    procedure twasmreader.HandleInstruction;
+      begin
+        case actasmtoken of
+          AS_LPAREN:
+            begin
+              Consume(AS_LPAREN);
+              HandleFoldedInstruction;
+            end;
+          AS_OPCODE:
+            begin
+              case actopcode of
+                a_block,
+                a_loop,
+                a_if:
+                  HandleBlockInstruction;
+                else
+                  HandlePlainInstruction;
+              end;
+            end;
+          else
+            {error};
+        end;
+      end;
+
+
+    procedure twasmreader.HandleFoldedInstruction;
+      var
+        HasLabel, HasType, HasParam, HasResult, HasInstructions,
+          HasThen, HasElse: Boolean;
+        instr: TWasmInstruction;
+        tmpS: string;
+      begin
+        //Consume(AS_LPAREN);
+        case actasmtoken of
+          AS_OPCODE:
+            begin
+              case actopcode of
+                a_block,
+                a_loop,
+                a_if:
+                  begin
+                    Consume(AS_OPCODE);
+                    HasType:=False;
+                    HasParam:=False;
+                    HasResult:=False;
+                    HasInstructions:=False;
+                    HasThen:=False;
+                    HasElse:=False;
+                    instr:=TWasmInstruction.create(TWasmOperand);
+                    instr.opcode:=actopcode;
+                    HasLabel:=False;
+                    if actasmtoken=AS_ID then
+                      begin
+                        Consume(AS_ID);
+                        HasLabel:=True;
+                      end;
+                    repeat
+                      case actasmtoken of
+                        AS_LPAREN:
+                          begin
+                            Consume(AS_LPAREN);
+                            case actasmtoken of
+                              AS_TYPE:
+                                begin
+                                  if HasElse or HasThen or HasInstructions or HasResult or HasParam or HasType then
+                                    begin
+                                      {TODO: error}
+                                    end;
+                                  Consume(AS_TYPE);
+                                  //TODO: consume u32 or id
+                                  Consume(actasmtoken);
+                                  Consume(AS_RPAREN);
+                                end;
+                              AS_PARAM:
+                                begin
+                                  if HasElse or HasThen or HasInstructions or HasResult then
+                                    begin
+                                      {TODO: error}
+                                    end;
+                                  Consume(AS_PARAM);
+                                  if actasmtoken=AS_ID then
+                                    begin
+                                      tmpS:=actasmpattern;
+                                      Consume(AS_ID);
+                                      if actasmtoken=AS_VALTYPE then
+                                        instr.AddParam(actasmpattern,actwasmbasictype);
+                                      Consume(AS_VALTYPE);
+                                    end
+                                  else
+                                    begin
+                                      while actasmtoken<>AS_RPAREN do
+                                        begin
+                                          if actasmtoken=AS_VALTYPE then
+                                            instr.AddParam('',actwasmbasictype);
+                                          Consume(AS_VALTYPE);
+                                        end;
+                                    end;
+                                  Consume(AS_RPAREN);
+                                end;
+                              AS_RESULT:
+                                begin
+                                  if HasElse or HasThen or HasInstructions then
+                                    begin
+                                      {TODO: error}
+                                    end;
+                                  Consume(AS_RESULT);
+                                  while actasmtoken<>AS_RPAREN do
+                                    begin
+                                      if actasmtoken=AS_VALTYPE then
+                                        instr.AddResult(actwasmbasictype);
+                                      Consume(AS_VALTYPE);
+                                    end;
+                                  Consume(AS_RPAREN);
+                                end;
+                              AS_THEN:
+                                begin
+                                  if instr.opcode<>a_if then
+                                    {error!};
+                                  Consume(AS_THEN);
+                                  HasThen:=True;
+                                  while actasmtoken<>AS_RPAREN do
+                                    HandleInstruction;
+                                  Consume(AS_RPAREN);
+                                end;
+                              AS_ELSE:
+                                begin
+                                  if instr.opcode<>a_if then
+                                    {error!};
+                                  Consume(AS_ELSE);
+                                  HasElse:=True;
+                                  while actasmtoken<>AS_RPAREN do
+                                    HandleInstruction;
+                                  Consume(AS_RPAREN);
+                                end;
+                              else
+                                begin
+                                  HasInstructions:=True;
+                                  HandleFoldedInstruction;
+                                end;
+                            end;
+                          end;
+                      end;
+                    until false;
+                  end;
+                else
+                  begin
+                    HandlePlainInstruction;
+                    {todo: parse next folded instructions, insert plain instruction after these}
+                  end;
+              end;
+            end;
+          else
+            {error}
+        end;
+      end;
+
+
+    procedure twasmreader.HandlePlainInstruction;
+      var
+        instr: TWasmInstruction;
+      begin
+        case actasmtoken of
+          AS_OPCODE:
+            begin
+              instr:=TWasmInstruction.create(TWasmOperand);
+              instr.opcode:=actopcode;
+              case actopcode of
+                { instructions, which require 0 operands }
+                a_nop,
+                a_unreachable,
+                a_return,
+                a_ref_is_null,
+                a_drop,
+                a_memory_size,
+                a_memory_grow,
+                a_memory_fill,
+                a_memory_copy,
+                a_i32_clz,a_i32_ctz,a_i32_popcnt,a_i32_add,a_i32_sub,a_i32_mul,a_i32_div_s,a_i32_div_u,a_i32_rem_s,a_i32_rem_u,a_i32_and,a_i32_or,a_i32_xor,a_i32_shl,a_i32_shr_s,a_i32_shr_u,a_i32_rotl,a_i32_rotr,
+                a_i64_clz,a_i64_ctz,a_i64_popcnt,a_i64_add,a_i64_sub,a_i64_mul,a_i64_div_s,a_i64_div_u,a_i64_rem_s,a_i64_rem_u,a_i64_and,a_i64_or,a_i64_xor,a_i64_shl,a_i64_shr_s,a_i64_shr_u,a_i64_rotl,a_i64_rotr,
+                a_f32_abs,a_f32_neg,a_f32_ceil,a_f32_floor,a_f32_trunc,a_f32_nearest,a_f32_sqrt,a_f32_add,a_f32_sub,a_f32_mul,a_f32_div,a_f32_min,a_f32_max,a_f32_copysign,
+                a_f64_abs,a_f64_neg,a_f64_ceil,a_f64_floor,a_f64_trunc,a_f64_nearest,a_f64_sqrt,a_f64_add,a_f64_sub,a_f64_mul,a_f64_div,a_f64_min,a_f64_max,a_f64_copysign,
+                a_i32_eqz,a_i32_eq,a_i32_ne,a_i32_lt_s,a_i32_lt_u,a_i32_gt_s,a_i32_gt_u,a_i32_le_s,a_i32_le_u,a_i32_ge_s,a_i32_ge_u,
+                a_i64_eqz,a_i64_eq,a_i64_ne,a_i64_lt_s,a_i64_lt_u,a_i64_gt_s,a_i64_gt_u,a_i64_le_s,a_i64_le_u,a_i64_ge_s,a_i64_ge_u,
+                a_f32_eq,a_f32_ne,a_f32_lt,a_f32_gt,a_f32_le,a_f32_ge,
+                a_f64_eq,a_f64_ne,a_f64_lt,a_f64_gt,a_f64_le,a_f64_ge,
+
+                a_i32_wrap_i64,
+                a_i32_trunc_f32_s,
+                a_i32_trunc_f32_u,
+                a_i32_trunc_f64_s,
+                a_i32_trunc_f64_u,
+                a_i32_trunc_sat_f32_s,
+                a_i32_trunc_sat_f32_u,
+                a_i32_trunc_sat_f64_s,
+                a_i32_trunc_sat_f64_u,
+                a_i64_extend_i32_s,
+                a_i64_extend_i32_u,
+                a_i64_trunc_f32_s,
+                a_i64_trunc_f32_u,
+                a_i64_trunc_f64_s,
+                a_i64_trunc_f64_u,
+                a_i64_trunc_sat_f32_s,
+                a_i64_trunc_sat_f32_u,
+                a_i64_trunc_sat_f64_u,
+                a_i64_trunc_sat_f64_s,
+                a_f32_convert_i32_s,
+                a_f32_convert_i32_u,
+                a_f32_convert_i64_s,
+                a_f32_convert_i64_u,
+                a_f32_demote_f64,
+                a_f64_convert_i32_s,
+                a_f64_convert_i32_u,
+                a_f64_convert_i64_s,
+                a_f64_convert_i64_u,
+                a_f64_promote_f32,
+                a_i32_reinterpret_f32,
+                a_i64_reinterpret_f64,
+                a_f32_reinterpret_i32,
+                a_f64_reinterpret_i64,
+
+                a_i32_extend8_s,
+                a_i32_extend16_s,
+                a_i64_extend8_s,
+                a_i64_extend16_s,
+                a_i64_extend32_s:
+                  ;
+              end;
+            end;
+          else
+            {error};
+        end;
+      end;
+
+
     function twasmreader.Assemble: tlinkedlist;
     function twasmreader.Assemble: tlinkedlist;
       begin
       begin
         Message1(asmr_d_start_reading,'WebAssembly');
         Message1(asmr_d_start_reading,'WebAssembly');