summaryrefslogtreecommitdiff
path: root/compiler/wasm32/wasmdef.pas
blob: 0fc027070299904d8b560cc6bb5ca80d86cbec60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
unit wasmdef;

{$i fpcdefs.inc}

interface

uses
  symtype, symsym, symdef, symconst, constexp
  ,defutil, procdefutil, cclasses;

type

    { TWasmTypeEntry }

    TWasmTypeEntry = class(Tobject)
      name : string; // always empty
      idx  : integer;
      constructor Create(aidx: integer; aname: string);
    end;

    { TWasmProcTypeLookup }

    TWasmProcTypeLookup = class(TObject)
      list: TFPHashObjectList;
      idx: integer;
      constructor Create(astartIndex: integer = 0);
      destructor Destroy; override;
      function GetTypeIndex(const typecode: string): Integer;
    end;


    // encodes procedure definition to a code used for the proc type lookup
    // it's case-sensitive!!!
    // i = i32, I = i64, f = f32, F = f32
    function WasmGetTypeCodeForDef(def: tdef; var ch: char): Boolean;

    function WasmGetTypeCode(aprocdef: tabstractprocdef): string;

    { returns whether a def always resides in memory,
      rather than in wasm local variables...) }
    function wasmAlwayInMem(def: tdef): boolean;

    function get_para_push_size(def: tdef): tdef;

implementation

  function get_para_push_size(def: tdef): tdef;
    begin
      result:=def;
      if def.typ=orddef then
        case torddef(def).ordtype of
          u8bit,uchar:
            if torddef(def).high>127 then
              result:=s8inttype;
          u16bit:
            begin
              if torddef(def).high>32767 then
                result:=s16inttype;
            end
          else
            ;
        end;
    end;

  function wasmAlwayInMem(def: tdef): boolean;
    begin
      case def.typ of
        arraydef,
        filedef,
        recorddef,
        objectdef,
        stringdef:
          result:=true;
        else
          result:=false;
      end;
    end;

  function WasmGetTypeCodeForDef(def: tdef; var ch: char): Boolean;
  begin
    Result := assigned(def);
    if not Result then Exit;

    case def.typ of
      floatdef:
        if def.size = 4 then ch :='f'
        else ch :='F';
      orddef:
        if def.size = 8 then ch :='I'
        else ch := 'i';
      // todo: set can be bigger
    else
      ch:='i'; // by address
    end;
  end;

  function WasmGetTypeCode(aprocdef: tabstractprocdef): string;
    var
      ch : char;
      i  : integer;
    begin
      Result := '';
      if not Assigned(aprocdef) then exit;

      for i:=0 to aprocdef.paras.Count-1 do begin
        WasmGetTypeCodeForDef( tparavarsym(aprocdef.paras[i]).paraloc[callerside].Def, ch);
        result:=result+ch;
      end;

      if assigned(aprocdef) then begin
        result:=result+':';
        WasmGetTypeCodeForDef(aprocdef.returndef, ch);
        result:=result+ch;
      end;

    end;

    { TWasmTypeEntry }

     constructor TWasmTypeEntry.Create(aidx: integer; aname: string);
      begin
        idx := aidx;
        name := aname;
      end;

  { TWasmProcTypeLookup }

    constructor TWasmProcTypeLookup.Create(astartIndex: integer = 0);
      begin
        inherited Create;
        list := TFPHashObjectList.Create(true);
        idx := astartIndex;
      end;

    destructor TWasmProcTypeLookup.Destroy;
      begin
        list.Free;
        inherited Destroy;
      end;

    function TWasmProcTypeLookup.GetTypeIndex(const typecode: string): Integer;
      var
        en : TWasmTypeEntry;
      begin
        en := TWasmTypeEntry(list.Find(typecode));
        if not Assigned(en) then begin
          en := TWasmTypeEntry.Create(idx, ''); // no need to copy
          inc(idx);
          list.Add(typecode, en);
        end;
        Result := en.idx;
      end;


end.