Coverage Report

Created: 2026-08-13 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm3/source/m3_compile.h
Line
Count
Source
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
    bool                isInitExpr;                 // walking a constant expression, not a function body
120
}
121
M3Compilation;
122
123
typedef M3Compilation *                 IM3Compilation;
124
125
typedef M3Result (* M3Compiler)         (IM3Compilation, m3opcode_t);
126
127
128
//-----------------------------------------------------------------------------------------------------------------------------------
129
130
131
typedef struct M3OpInfo
132
{
133
#ifdef DEBUG
134
    const char * const      name;
135
#endif
136
137
    i8                      stackOffset;
138
    u8                      type;
139
140
    // for most operations:
141
    // [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack
142
    IM3Operation            operations [4];
143
144
    M3Compiler              compiler;
145
}
146
M3OpInfo;
147
148
typedef const M3OpInfo *    IM3OpInfo;
149
150
IM3OpInfo  GetOpInfo  (m3opcode_t opcode);
151
152
// TODO: This helper should be removed, when MultiValue is implemented
153
static inline
154
0
u8 GetSingleRetType(IM3FuncType ftype) {
155
0
    return (ftype && ftype->numRets) ? ftype->types[0] : (u8)c_m3Type_none;
156
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
Unexecuted instantiation: m3_validate.c:GetSingleRetType
157
158
static const u16 c_m3RegisterUnallocated = 0;
159
static const u16 c_slotUnused = 0xffff;
160
161
static inline
162
bool  IsRegisterAllocated  (IM3Compilation o, u32 i_register)
163
1
{
164
1
    return (o->regStackIndexPlusOne [i_register] != c_m3RegisterUnallocated);
165
1
}
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
163
1
{
164
1
    return (o->regStackIndexPlusOne [i_register] != c_m3RegisterUnallocated);
165
1
}
Unexecuted instantiation: m3_core.c:IsRegisterAllocated
Unexecuted instantiation: m3_validate.c:IsRegisterAllocated
166
167
static inline
168
bool  IsStackPolymorphic  (IM3Compilation o)
169
69
{
170
69
    return o->block.isPolymorphic;
171
69
}
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
169
69
{
170
69
    return o->block.isPolymorphic;
171
69
}
Unexecuted instantiation: m3_core.c:IsStackPolymorphic
Unexecuted instantiation: m3_validate.c:IsStackPolymorphic
172
173
522
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
173
522
static inline bool  IsRegisterSlotAlias        (u16 i_slot)    { return (i_slot >= d_m3Reg0SlotAlias and i_slot != c_slotUnused); }
Unexecuted instantiation: m3_core.c:IsRegisterSlotAlias
Unexecuted instantiation: m3_validate.c:IsRegisterSlotAlias
174
2
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
174
2
static inline bool  IsFpRegisterSlotAlias      (u16 i_slot)    { return (i_slot == d_m3Fp0SlotAlias);  }
Unexecuted instantiation: m3_core.c:IsFpRegisterSlotAlias
Unexecuted instantiation: m3_validate.c:IsFpRegisterSlotAlias
175
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
Unexecuted instantiation: m3_validate.c:IsIntRegisterSlotAlias
176
177
178
#ifdef DEBUG
179
    #define M3OP(...)       { __VA_ARGS__ }
180
    #define M3OP_RESERVED   { "reserved" }
181
#else
182
    // Strip-off name
183
    #define M3OP(name, ...) { __VA_ARGS__ }
184
    #define M3OP_RESERVED   { 0 }
185
#endif
186
187
#if d_m3HasFloat
188
    #define M3OP_F          M3OP
189
#elif d_m3NoFloatDynamic
190
    #define M3OP_F(n,o,t,op,...)        M3OP(n, o, t, { op_Unsupported, op_Unsupported, op_Unsupported, op_Unsupported }, __VA_ARGS__)
191
#else
192
    #define M3OP_F(...)     { 0 }
193
#endif
194
195
//-----------------------------------------------------------------------------------------------------------------------------------
196
197
u16         GetMaxUsedSlotPlusOne       (IM3Compilation o);
198
199
M3Result    CompileBlock                (IM3Compilation io, IM3FuncType i_blockType, m3opcode_t i_blockOpcode);
200
201
M3Result    CompileBlockStatements      (IM3Compilation io);
202
M3Result    CompileFunction             (IM3Function io_function);
203
204
M3Result    CompileRawFunction          (IM3Module io_module, IM3Function io_function, const void * i_function, const void * i_userdata);
205
206
d_m3EndExternC
207
208
#endif // m3_compile_h