2929#include < cassert>
3030#include < cstddef>
3131#include < cstdint>
32+ #include < limits>
3233
3334#include " ../interpreter/bytecodes.h"
3435#include " ../vm/Globals.h"
3940#include " ../vmobjects/VMMethod.h"
4041#include " ../vmobjects/VMSymbol.h"
4142#include " MethodGenerationContext.h"
43+ #include " Parser.h"
4244
4345void Emit1 (MethodGenerationContext& mgenc, uint8_t bytecode,
4446 int64_t stackEffect) {
4547 mgenc.AddBytecode (bytecode, stackEffect);
4648}
4749
48- void Emit2 (MethodGenerationContext& mgenc, uint8_t bytecode, size_t idx,
50+ void Emit2 (MethodGenerationContext& mgenc, uint8_t bytecode, uint8_t idx,
4951 int64_t stackEffect) {
5052 mgenc.AddBytecode (bytecode, stackEffect);
5153 mgenc.AddBytecodeArgument (idx);
5254}
5355
54- void Emit3 (MethodGenerationContext& mgenc, uint8_t bytecode, size_t idx,
56+ void Emit3 (MethodGenerationContext& mgenc, uint8_t bytecode, uint8_t idx,
5557 size_t ctx, int64_t stackEffect) {
5658 mgenc.AddBytecode (bytecode, stackEffect);
5759 mgenc.AddBytecodeArgument (idx);
@@ -66,9 +68,23 @@ void EmitDUP(MethodGenerationContext& mgenc) {
6668 Emit1 (mgenc, BC_DUP, 1 );
6769}
6870
69- void EmitPUSHLOCAL (MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
70- assert (idx >= 0 );
71- assert (ctx >= 0 );
71+ void EmitPUSHLOCAL (MethodGenerationContext& mgenc, const Parser& parser,
72+ size_t index, size_t context) {
73+ if (index > std::numeric_limits<uint8_t >::max ()) {
74+ parser.ParseError (
75+ " The method has too many local variables. You may be able to split "
76+ " up this method into multiple to avoid the issue." );
77+ }
78+
79+ if (context > std::numeric_limits<uint8_t >::max ()) {
80+ parser.ParseError (
81+ " This block is too deeply nested. You may be able to split up this "
82+ " method into multiple to avoid the issue." );
83+ }
84+
85+ const uint8_t idx = index;
86+ const uint8_t ctx = context;
87+
7288 if (ctx == 0 ) {
7389 if (idx == 0 ) {
7490 Emit1 (mgenc, BC_PUSH_LOCAL_0, 1 );
@@ -86,9 +102,22 @@ void EmitPUSHLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
86102 Emit3 (mgenc, BC_PUSH_LOCAL, idx, ctx, 1 );
87103}
88104
89- void EmitPUSHARGUMENT (MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
90- assert (idx >= 0 );
91- assert (ctx >= 0 );
105+ void EmitPUSHARGUMENT (MethodGenerationContext& mgenc, const Parser& parser,
106+ size_t index, size_t context) {
107+ if (index > std::numeric_limits<uint8_t >::max ()) {
108+ parser.ParseError (
109+ " The method has too many arguments. You may be able to split up "
110+ " this method into multiple to avoid the issue." );
111+ }
112+
113+ if (context > std::numeric_limits<uint8_t >::max ()) {
114+ parser.ParseError (
115+ " This block is too deeply nested. You may be able to split up this "
116+ " method into multiple to avoid the issue." );
117+ }
118+
119+ const uint8_t idx = index;
120+ const uint8_t ctx = context;
92121
93122 if (ctx == 0 ) {
94123 if (idx == 0 ) {
@@ -109,23 +138,27 @@ void EmitPUSHARGUMENT(MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
109138 Emit3 (mgenc, BC_PUSH_ARGUMENT, idx, ctx, 1 );
110139}
111140
112- void EmitPUSHFIELD (MethodGenerationContext& mgenc, VMSymbol* field) {
113- const uint8_t idx = mgenc. GetFieldIndex ( field);
114- if ( idx == 0 ) {
115- Emit1 (mgenc, BC_PUSH_FIELD_0, 1 );
116- } else if (idx == 1 ) {
117- Emit1 (mgenc, BC_PUSH_FIELD_1, 1 );
118- } else {
119- Emit2 (mgenc, BC_PUSH_FIELD, idx, 1 );
141+ void EmitPUSHFIELD (MethodGenerationContext& mgenc, const Parser& parser,
142+ VMSymbol* field) {
143+ const int64_t idx = mgenc. GetFieldIndex (field);
144+ if (idx < 0 || idx > std::numeric_limits< uint8_t >:: max ()) {
145+ parser. ParseError (
146+ " The method tries to access a field that cannot be represented in "
147+ " the SOM++ bytecodes. Make sure this class and its superclasses "
148+ " have less than 256 fields in total. " );
120149 }
150+
151+ EmitPushFieldWithIndex (mgenc, idx);
121152}
122153
123- void EmitPUSHBLOCK (MethodGenerationContext& mgenc, VMInvokable* block) {
124- const uint8_t idx = mgenc.AddLiteralIfAbsent (block);
154+ void EmitPUSHBLOCK (MethodGenerationContext& mgenc, const Parser& parser,
155+ VMInvokable* block) {
156+ const uint8_t idx = mgenc.AddLiteralIfAbsent (block, parser);
125157 Emit2 (mgenc, BC_PUSH_BLOCK, idx, 1 );
126158}
127159
128- void EmitPUSHCONSTANT (MethodGenerationContext& mgenc, vm_oop_t cst) {
160+ void EmitPUSHCONSTANT (MethodGenerationContext& mgenc, const Parser& parser,
161+ vm_oop_t cst) {
129162 // this isn't very robust with respect to initialization order
130163 // so, we check here, and hope it's working, but alternatively
131164 // we also make sure that we don't miss anything in the else
@@ -148,7 +181,7 @@ void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, vm_oop_t cst) {
148181 return ;
149182 }
150183
151- const uint8_t idx = mgenc.AddLiteralIfAbsent (cst);
184+ const uint8_t idx = mgenc.AddLiteralIfAbsent (cst, parser );
152185 if (idx == 0 ) {
153186 Emit1 (mgenc, BC_PUSH_CONSTANT_0, 1 );
154187 return ;
@@ -173,15 +206,16 @@ void EmitPUSHCONSTANTString(MethodGenerationContext& mgenc, VMString* str) {
173206 Emit2 (mgenc, BC_PUSH_CONSTANT, mgenc.FindLiteralIndex (str), 1 );
174207}
175208
176- void EmitPUSHGLOBAL (MethodGenerationContext& mgenc, VMSymbol* global) {
209+ void EmitPUSHGLOBAL (MethodGenerationContext& mgenc, const Parser& parser,
210+ VMSymbol* global) {
177211 if (global == SymbolFor (" nil" )) {
178- EmitPUSHCONSTANT (mgenc, load_ptr (nilObject));
212+ EmitPUSHCONSTANT (mgenc, parser, load_ptr (nilObject));
179213 } else if (global == SymbolFor (" true" )) {
180- EmitPUSHCONSTANT (mgenc, load_ptr (trueObject));
214+ EmitPUSHCONSTANT (mgenc, parser, load_ptr (trueObject));
181215 } else if (global == SymbolFor (" false" )) {
182- EmitPUSHCONSTANT (mgenc, load_ptr (falseObject));
216+ EmitPUSHCONSTANT (mgenc, parser, load_ptr (falseObject));
183217 } else {
184- const uint8_t idx = mgenc.AddLiteralIfAbsent (global);
218+ const uint8_t idx = mgenc.AddLiteralIfAbsent (global, parser );
185219 Emit2 (mgenc, BC_PUSH_GLOBAL, idx, 1 );
186220 }
187221}
@@ -192,9 +226,23 @@ void EmitPOP(MethodGenerationContext& mgenc) {
192226 }
193227}
194228
195- void EmitPOPLOCAL (MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
196- assert (idx >= 0 );
197- assert (ctx >= 0 );
229+ void EmitPOPLOCAL (MethodGenerationContext& mgenc, const Parser& parser,
230+ size_t index, size_t context) {
231+ if (index > std::numeric_limits<uint8_t >::max ()) {
232+ parser.ParseError (
233+ " The method has too many local variables. You may be able to split "
234+ " up this method into multiple to avoid the issue." );
235+ }
236+
237+ if (context > std::numeric_limits<uint8_t >::max ()) {
238+ parser.ParseError (
239+ " This block is too deeply nested. You may be able to split up this "
240+ " method into multiple to avoid the issue." );
241+ }
242+
243+ const uint8_t idx = index;
244+ const uint8_t ctx = context;
245+
198246 if (ctx == 0 ) {
199247 if (idx == 0 ) {
200248 Emit1 (mgenc, BC_POP_LOCAL_0, -1 );
@@ -215,12 +263,32 @@ void EmitPOPLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
215263 Emit3 (mgenc, BC_POP_LOCAL, idx, ctx, -1 );
216264}
217265
218- void EmitPOPARGUMENT (MethodGenerationContext& mgenc, size_t idx, size_t ctx) {
266+ void EmitPOPARGUMENT (MethodGenerationContext& mgenc, const Parser& parser,
267+ size_t idx, size_t ctx) {
268+ if (idx > std::numeric_limits<uint8_t >::max ()) {
269+ parser.ParseError (
270+ " The method has too many arguments. You may be able to split up "
271+ " this method into multiple to avoid the issue." );
272+ }
273+
274+ if (ctx > std::numeric_limits<uint8_t >::max ()) {
275+ parser.ParseError (
276+ " This block is too deeply nested. You may be able to split up this "
277+ " method into multiple to avoid the issue." );
278+ }
279+
219280 Emit3 (mgenc, BC_POP_ARGUMENT, idx, ctx, -1 );
220281}
221282
222- void EmitPOPFIELD (MethodGenerationContext& mgenc, VMSymbol* field) {
223- const uint8_t idx = mgenc.GetFieldIndex (field);
283+ void EmitPOPFIELD (MethodGenerationContext& mgenc, const Parser& parser,
284+ VMSymbol* field) {
285+ const int64_t idx = mgenc.GetFieldIndex (field);
286+ if (idx < 0 || idx > std::numeric_limits<uint8_t >::max ()) {
287+ parser.ParseError (
288+ " The method tries to access a field that cannot be represented in "
289+ " the SOM++ bytecodes. Make sure this class and its superclasses "
290+ " have less than 256 fields in total." );
291+ }
224292
225293 if (mgenc.OptimizeIncField (idx)) {
226294 return ;
@@ -229,17 +297,19 @@ void EmitPOPFIELD(MethodGenerationContext& mgenc, VMSymbol* field) {
229297 EmitPopFieldWithIndex (mgenc, idx);
230298}
231299
232- void EmitSEND (MethodGenerationContext& mgenc, VMSymbol* msg) {
233- const uint8_t idx = mgenc.AddLiteralIfAbsent (msg);
300+ void EmitSEND (MethodGenerationContext& mgenc, const Parser& parser,
301+ VMSymbol* msg) {
302+ const uint8_t idx = mgenc.AddLiteralIfAbsent (msg, parser);
234303
235304 const uint8_t numArgs = Signature::GetNumberOfArguments (msg);
236305 const int64_t stackEffect = -numArgs + 1 ; // +1 for the result
237306
238307 Emit2 (mgenc, numArgs == 1 ? BC_SEND_1 : BC_SEND, idx, stackEffect);
239308}
240309
241- void EmitSUPERSEND (MethodGenerationContext& mgenc, VMSymbol* msg) {
242- const uint8_t idx = mgenc.AddLiteralIfAbsent (msg);
310+ void EmitSUPERSEND (MethodGenerationContext& mgenc, const Parser& parser,
311+ VMSymbol* msg) {
312+ const uint8_t idx = mgenc.AddLiteralIfAbsent (msg, parser);
243313 const uint8_t numArgs = Signature::GetNumberOfArguments (msg);
244314 const int64_t stackEffect = -numArgs + 1 ; // +1 for the result
245315
@@ -251,8 +321,8 @@ void EmitRETURNSELF(MethodGenerationContext& mgenc) {
251321 Emit1 (mgenc, BC_RETURN_SELF, 0 );
252322}
253323
254- void EmitRETURNLOCAL (MethodGenerationContext& mgenc) {
255- if (!mgenc.OptimizeReturnField ()) {
324+ void EmitRETURNLOCAL (MethodGenerationContext& mgenc, const Parser& parser ) {
325+ if (!mgenc.OptimizeReturnField (parser )) {
256326 Emit1 (mgenc, BC_RETURN_LOCAL, 0 );
257327 }
258328}
@@ -261,18 +331,21 @@ void EmitRETURNNONLOCAL(MethodGenerationContext& mgenc) {
261331 Emit1 (mgenc, BC_RETURN_NON_LOCAL, 0 );
262332}
263333
264- void EmitRETURNFIELD (MethodGenerationContext& mgenc, size_t index) {
265- assert (index <= 2 );
334+ void EmitRETURNFIELD (MethodGenerationContext& mgenc, const Parser& parser,
335+ size_t index) {
336+ if (index > 2 ) {
337+ parser.ParseError (
338+ " Internal Error: EmitRETURNFIELD has unsupported argument" );
339+ }
340+
266341 uint8_t bc = 0 ;
267342 switch (index) {
268343 case 0 :
269344 bc = BC_RETURN_FIELD_0;
270345 break ;
271-
272346 case 1 :
273347 bc = BC_RETURN_FIELD_1;
274348 break ;
275-
276349 case 2 :
277350 bc = BC_RETURN_FIELD_2;
278351 break ;
0 commit comments