Coverage Report

Created: 2025-09-05 06:58

/src/wasm3/source/m3_compile.h
Line
Count
Source (jump to first uncovered line)
1
//
2
//  m3_compile.h
3
//
4
//  Created by Steven Massey on 4/17/19.
5
//  Copyright © 2019 Steven Massey. All rights reserved.
6
//
7
8
#ifndef m3_compile_h
9
#define m3_compile_h
10
11
#include "m3_code.h"
12
#include "m3_exec_defs.h"
13
#include "m3_function.h"
14
15
d_m3BeginExternC
16
17
enum
18
{
19
    c_waOp_block                = 0x02,
20
    c_waOp_loop                 = 0x03,
21
    c_waOp_if                   = 0x04,
22
    c_waOp_else                 = 0x05,
23
    c_waOp_end                  = 0x0b,
24
    c_waOp_branch               = 0x0c,
25
    c_waOp_branchTable          = 0x0e,
26
    c_waOp_branchIf             = 0x0d,
27
    c_waOp_call                 = 0x10,
28
    c_waOp_getLocal             = 0x20,
29
    c_waOp_setLocal             = 0x21,
30
    c_waOp_teeLocal             = 0x22,
31
32
    c_waOp_getGlobal            = 0x23,
33
34
    c_waOp_store_f32            = 0x38,
35
    c_waOp_store_f64            = 0x39,
36
37
    c_waOp_i32_const            = 0x41,
38
    c_waOp_i64_const            = 0x42,
39
    c_waOp_f32_const            = 0x43,
40
    c_waOp_f64_const            = 0x44,
41
42
    c_waOp_extended             = 0xfc,
43
44
    c_waOp_memoryCopy           = 0xfc0a,
45
    c_waOp_memoryFill           = 0xfc0b
46
};
47
48
49
0
#define d_FuncRetType(ftype,i)  ((ftype)->types[(i)])
50
0
#define d_FuncArgType(ftype,i)  ((ftype)->types[(ftype)->numRets + (i)])
51
52
//-----------------------------------------------------------------------------------------------------------------------------------
53
54
typedef struct M3CompilationScope
55
{
56
    struct M3CompilationScope *     outer;
57
58
    pc_t                            pc;                 // used by ContinueLoop's
59
    pc_t                            patches;
60
    i32                             depth;
61
    u16                             exitStackIndex;
62
    u16                             blockStackIndex;
63
//    u16                             topSlot;
64
    IM3FuncType                     type;
65
    m3opcode_t                      opcode;
66
    bool                            isPolymorphic;
67
}
68
M3CompilationScope;
69
70
typedef M3CompilationScope *        IM3CompilationScope;
71
72
typedef struct
73
{
74
    IM3Runtime          runtime;
75
    IM3Module           module;
76
77
    bytes_t             wasm;
78
    bytes_t             wasmEnd;
79
    bytes_t             lastOpcodeStart;
80
81
    M3CompilationScope  block;
82
83
    IM3Function         function;
84
85
    IM3CodePage         page;
86
87
#ifdef DEBUG
88
    u32                 numEmits;
89
    u32                 numOpcodes;
90
#endif
91
92
    u16                 stackFirstDynamicIndex;     // args and locals are pushed to the stack so that their slot locations can be tracked. the wasm model itself doesn't
93
                                                    // treat these values as being on the stack, so stackFirstDynamicIndex marks the start of the real Wasm stack
94
    u16                 stackIndex;                 // current stack top
95
96
    u16                 slotFirstConstIndex;
97
    u16                 slotMaxConstIndex;          // as const's are encountered during compilation this tracks their location in the "real" stack
98
99
    u16                 slotFirstLocalIndex;
100
    u16                 slotFirstDynamicIndex;      // numArgs + numLocals + numReservedConstants. the first mutable slot available to the compiler.
101
102
    u16                 maxStackSlots;
103
104
    m3slot_t            constants                   [d_m3MaxConstantTableSize];
105
106
    // 'wasmStack' holds slot locations
107
    u16                 wasmStack                   [d_m3MaxFunctionStackHeight];
108
    u8                  typeStack                   [d_m3MaxFunctionStackHeight];
109
110
    // 'm3Slots' contains allocation usage counts
111
    u8                  m3Slots                     [d_m3MaxFunctionSlots];
112
113
    u16                 slotMaxAllocatedIndexPlusOne;
114
115
    u16                 regStackIndexPlusOne        [2];
116
117
    m3opcode_t          previousOpcode;
118
}
119
M3Compilation;
120
121
typedef M3Compilation *                 IM3Compilation;
122
123
typedef M3Result (* M3Compiler)         (IM3Compilation, m3opcode_t);
124
125
126
//-----------------------------------------------------------------------------------------------------------------------------------
127
128
129
typedef struct M3OpInfo
130
{
131
#ifdef DEBUG
132
    const char * const      name;
133
#endif
134
135
    i8                      stackOffset;
136
    u8                      type;
137
138
    // for most operations:
139
    // [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack
140
    IM3Operation            operations [4];
141
142
    M3Compiler              compiler;
143
}
144
M3OpInfo;
145
146
typedef const M3OpInfo *    IM3OpInfo;
147
148
IM3OpInfo  GetOpInfo  (m3opcode_t opcode);
149
150
// TODO: This helper should be removed, when MultiValue is implemented
151
static inline
152
0
u8 GetSingleRetType(IM3FuncType ftype) {
153
0
    return (ftype && ftype->numRets) ? ftype->types[0] : (u8)c_m3Type_none;
154
0
}
Unexecuted instantiation: m3_env.c:GetSingleRetType
Unexecuted instantiation: m3_function.c:GetSingleRetType
Unexecuted instantiation: m3_info.c:GetSingleRetType
Unexecuted instantiation: m3_module.c:GetSingleRetType
Unexecuted instantiation: m3_parse.c:GetSingleRetType
Unexecuted instantiation: m3_code.c:GetSingleRetType
Unexecuted instantiation: m3_compile.c:GetSingleRetType
Unexecuted instantiation: m3_core.c:GetSingleRetType
155
156
static const u16 c_m3RegisterUnallocated = 0;
157
static const u16 c_slotUnused = 0xffff;
158
159
static inline
160
bool  IsRegisterAllocated  (IM3Compilation o, u32 i_register)
161
1.29k
{
162
1.29k
    return (o->regStackIndexPlusOne [i_register] != c_m3RegisterUnallocated);
163
1.29k
}
Unexecuted instantiation: m3_env.c:IsRegisterAllocated
Unexecuted instantiation: m3_function.c:IsRegisterAllocated
Unexecuted instantiation: m3_info.c:IsRegisterAllocated
Unexecuted instantiation: m3_module.c:IsRegisterAllocated
Unexecuted instantiation: m3_parse.c:IsRegisterAllocated
Unexecuted instantiation: m3_code.c:IsRegisterAllocated
m3_compile.c:IsRegisterAllocated
Line
Count
Source
161
1.29k
{
162
1.29k
    return (o->regStackIndexPlusOne [i_register] != c_m3RegisterUnallocated);
163
1.29k
}
Unexecuted instantiation: m3_core.c:IsRegisterAllocated
164
165
static inline
166
bool  IsStackPolymorphic  (IM3Compilation o)
167
17.6k
{
168
17.6k
    return o->block.isPolymorphic;
169
17.6k
}
Unexecuted instantiation: m3_env.c:IsStackPolymorphic
Unexecuted instantiation: m3_function.c:IsStackPolymorphic
Unexecuted instantiation: m3_info.c:IsStackPolymorphic
Unexecuted instantiation: m3_module.c:IsStackPolymorphic
Unexecuted instantiation: m3_parse.c:IsStackPolymorphic
Unexecuted instantiation: m3_code.c:IsStackPolymorphic
m3_compile.c:IsStackPolymorphic
Line
Count
Source
167
17.6k
{
168
17.6k
    return o->block.isPolymorphic;
169
17.6k
}
Unexecuted instantiation: m3_core.c:IsStackPolymorphic
170
171
77.7k
static inline bool  IsRegisterSlotAlias        (u16 i_slot)    { return (i_slot >= d_m3Reg0SlotAlias and i_slot != c_slotUnused); }
Unexecuted instantiation: m3_env.c:IsRegisterSlotAlias
Unexecuted instantiation: m3_function.c:IsRegisterSlotAlias
Unexecuted instantiation: m3_info.c:IsRegisterSlotAlias
Unexecuted instantiation: m3_module.c:IsRegisterSlotAlias
Unexecuted instantiation: m3_parse.c:IsRegisterSlotAlias
Unexecuted instantiation: m3_code.c:IsRegisterSlotAlias
m3_compile.c:IsRegisterSlotAlias
Line
Count
Source
171
77.7k
static inline bool  IsRegisterSlotAlias        (u16 i_slot)    { return (i_slot >= d_m3Reg0SlotAlias and i_slot != c_slotUnused); }
Unexecuted instantiation: m3_core.c:IsRegisterSlotAlias
172
1.08k
static inline bool  IsFpRegisterSlotAlias      (u16 i_slot)    { return (i_slot == d_m3Fp0SlotAlias);  }
Unexecuted instantiation: m3_env.c:IsFpRegisterSlotAlias
Unexecuted instantiation: m3_function.c:IsFpRegisterSlotAlias
Unexecuted instantiation: m3_info.c:IsFpRegisterSlotAlias
Unexecuted instantiation: m3_module.c:IsFpRegisterSlotAlias
Unexecuted instantiation: m3_parse.c:IsFpRegisterSlotAlias
Unexecuted instantiation: m3_code.c:IsFpRegisterSlotAlias
m3_compile.c:IsFpRegisterSlotAlias
Line
Count
Source
172
1.08k
static inline bool  IsFpRegisterSlotAlias      (u16 i_slot)    { return (i_slot == d_m3Fp0SlotAlias);  }
Unexecuted instantiation: m3_core.c:IsFpRegisterSlotAlias
173
0
static inline bool  IsIntRegisterSlotAlias     (u16 i_slot)    { return (i_slot == d_m3Reg0SlotAlias); }
Unexecuted instantiation: m3_env.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_function.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_info.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_module.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_parse.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_code.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_compile.c:IsIntRegisterSlotAlias
Unexecuted instantiation: m3_core.c:IsIntRegisterSlotAlias
174
175
176
#ifdef DEBUG
177
    #define M3OP(...)       { __VA_ARGS__ }
178
    #define M3OP_RESERVED   { "reserved" }
179
#else
180
    // Strip-off name
181
    #define M3OP(name, ...) { __VA_ARGS__ }
182
    #define M3OP_RESERVED   { 0 }
183
#endif
184
185
#if d_m3HasFloat
186
    #define M3OP_F          M3OP
187
#elif d_m3NoFloatDynamic
188
    #define M3OP_F(n,o,t,op,...)        M3OP(n, o, t, { op_Unsupported, op_Unsupported, op_Unsupported, op_Unsupported }, __VA_ARGS__)
189
#else
190
    #define M3OP_F(...)     { 0 }
191
#endif
192
193
//-----------------------------------------------------------------------------------------------------------------------------------
194
195
u16         GetMaxUsedSlotPlusOne       (IM3Compilation o);
196
197
M3Result    CompileBlock                (IM3Compilation io, IM3FuncType i_blockType, m3opcode_t i_blockOpcode);
198
199
M3Result    CompileBlockStatements      (IM3Compilation io);
200
M3Result    CompileFunction             (IM3Function io_function);
201
202
M3Result    CompileRawFunction          (IM3Module io_module, IM3Function io_function, const void * i_function, const void * i_userdata);
203
204
d_m3EndExternC
205
206
#endif // m3_compile_h