@@ -36,7 +36,6 @@ using namespace solidity::frontend;
36
36
using namespace solidity ::langutil;
37
37
using namespace solidity ::util;
38
38
39
-
40
39
StackVariable::StackVariable (CompilerContext& _compilerContext, VariableDeclaration const & _declaration):
41
40
LValue(_compilerContext, _declaration.annotation().type),
42
41
m_baseStackOffset(m_context.baseStackOffsetOfVariable(_declaration)),
@@ -198,15 +197,17 @@ void ImmutableItem::setToZero(SourceLocation const&, bool _removeReference) cons
198
197
m_context << Instruction::POP;
199
198
}
200
199
201
- StorageItem::StorageItem (CompilerContext& _compilerContext, VariableDeclaration const & _declaration):
202
- StorageItem(_compilerContext, *_declaration.annotation().type)
200
+ template <bool IsTransient>
201
+ GenericStorageItem<IsTransient>::GenericStorageItem(CompilerContext& _compilerContext, VariableDeclaration const & _declaration):
202
+ GenericStorageItem<IsTransient>(_compilerContext, *_declaration.annotation().type)
203
203
{
204
204
solAssert (!_declaration.immutable (), " " );
205
205
auto const & location = m_context.storageLocationOfVariable (_declaration);
206
206
m_context << location.first << u256 (location.second );
207
207
}
208
208
209
- StorageItem::StorageItem (CompilerContext& _compilerContext, Type const & _type):
209
+ template <bool IsTransient>
210
+ GenericStorageItem<IsTransient>::GenericStorageItem(CompilerContext& _compilerContext, Type const & _type):
210
211
LValue (_compilerContext, &_type)
211
212
{
212
213
if (m_dataType->isValueType ())
@@ -217,11 +218,13 @@ StorageItem::StorageItem(CompilerContext& _compilerContext, Type const& _type):
217
218
}
218
219
}
219
220
220
- void StorageItem::retrieveValue (SourceLocation const &, bool _remove) const
221
+ template <bool IsTransient>
222
+ void GenericStorageItem<IsTransient>::retrieveValue(langutil::SourceLocation const &, bool _remove) const
221
223
{
222
224
// stack: storage_key storage_offset
223
225
if (!m_dataType->isValueType ())
224
226
{
227
+ solUnimplementedAssert (!IsTransient, " Transient storage reference types are not supported yet." );
225
228
solAssert (m_dataType->sizeOnStack () == 1 , " Invalid storage ref size." );
226
229
if (_remove)
227
230
m_context << Instruction::POP; // remove byte offset
@@ -232,20 +235,20 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
232
235
if (!_remove)
233
236
CompilerUtils (m_context).copyToStackTop (sizeOnStack (), sizeOnStack ());
234
237
if (m_dataType->storageBytes () == 32 )
235
- m_context << Instruction::POP << Instruction::SLOAD ;
238
+ m_context << Instruction::POP << s_loadInstruction ;
236
239
else
237
240
{
238
241
Type const * type = m_dataType;
239
242
if (type->category () == Type::Category::UserDefinedValueType)
240
243
type = type->encodingType ();
241
244
bool cleaned = false ;
242
245
m_context
243
- << Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1
246
+ << Instruction::SWAP1 << s_loadInstruction << Instruction::SWAP1
244
247
<< u256 (0x100 ) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV;
245
248
if (type->category () == Type::Category::FixedPoint )
246
249
// implementation should be very similar to the integer case.
247
250
solUnimplemented (" Not yet implemented - FixedPointType." );
248
- else if (FunctionType const * fun = dynamic_cast <decltype (fun) >(type))
251
+ else if (auto const * fun = dynamic_cast <FunctionType const * >(type))
249
252
{
250
253
if (fun->kind () == FunctionType::Kind::External)
251
254
{
@@ -281,7 +284,8 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
281
284
}
282
285
}
283
286
284
- void StorageItem::storeValue (Type const & _sourceType, SourceLocation const & _location, bool _move) const
287
+ template <bool IsTransient>
288
+ void GenericStorageItem<IsTransient>::storeValue(Type const & _sourceType, langutil::SourceLocation const & _location, bool _move) const
285
289
{
286
290
CompilerUtils utils (m_context);
287
291
solAssert (m_dataType, " " );
@@ -303,15 +307,15 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
303
307
utils.convertType (_sourceType, *m_dataType, true );
304
308
m_context << Instruction::SWAP1;
305
309
306
- m_context << Instruction::SSTORE ;
310
+ m_context << s_storeInstruction ;
307
311
}
308
312
else
309
313
{
310
314
// OR the value into the other values in the storage slot
311
315
m_context << u256 (0x100 ) << Instruction::EXP;
312
316
// stack: value storage_ref multiplier
313
317
// fetch old value
314
- m_context << Instruction::DUP2 << Instruction::SLOAD ;
318
+ m_context << Instruction::DUP2 << s_loadInstruction ;
315
319
// stack: value storage_ref multiplier old_full_value
316
320
// clear bytes in old value
317
321
m_context
@@ -358,13 +362,14 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
358
362
}
359
363
m_context << Instruction::MUL << Instruction::OR;
360
364
// stack: value storage_ref updated_value
361
- m_context << Instruction::SWAP1 << Instruction::SSTORE ;
365
+ m_context << Instruction::SWAP1 << s_storeInstruction ;
362
366
if (_move)
363
367
utils.popStackElement (*m_dataType);
364
368
}
365
369
}
366
370
else
367
371
{
372
+ solUnimplementedAssert (!IsTransient, " Transient storage reference types are not supported yet." );
368
373
solAssert (
369
374
_sourceType.category () == m_dataType->category (),
370
375
" Wrong type conversation for assignment."
@@ -445,16 +450,19 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
445
450
}
446
451
}
447
452
448
- void StorageItem::setToZero (SourceLocation const &, bool _removeReference) const
453
+ template <bool IsTransient>
454
+ void GenericStorageItem<IsTransient>::setToZero(langutil::SourceLocation const &, bool _removeReference) const
449
455
{
450
456
if (m_dataType->category () == Type::Category::Array)
451
457
{
458
+ solUnimplementedAssert (!IsTransient, " Transient storage reference types are not supported yet." );
452
459
if (!_removeReference)
453
460
CompilerUtils (m_context).copyToStackTop (sizeOnStack (), sizeOnStack ());
454
461
ArrayUtils (m_context).clearArray (dynamic_cast <ArrayType const &>(*m_dataType));
455
462
}
456
463
else if (m_dataType->category () == Type::Category::Struct)
457
464
{
465
+ solUnimplementedAssert (!IsTransient, " Transient storage reference types are not supported yet." );
458
466
// stack layout: storage_key storage_offset
459
467
// @todo this can be improved: use StorageItem for non-value types, and just store 0 in
460
468
// all slots that contain value types later.
@@ -484,22 +492,22 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
484
492
// offset should be zero
485
493
m_context
486
494
<< Instruction::POP << u256 (0 )
487
- << Instruction::SWAP1 << Instruction::SSTORE ;
495
+ << Instruction::SWAP1 << s_storeInstruction ;
488
496
}
489
497
else
490
498
{
491
499
m_context << u256 (0x100 ) << Instruction::EXP;
492
500
// stack: storage_ref multiplier
493
501
// fetch old value
494
- m_context << Instruction::DUP2 << Instruction::SLOAD ;
502
+ m_context << Instruction::DUP2 << s_loadInstruction ;
495
503
// stack: storage_ref multiplier old_full_value
496
504
// clear bytes in old value
497
505
m_context
498
506
<< Instruction::SWAP1 << ((u256 (1 ) << (8 * m_dataType->storageBytes ())) - 1 )
499
507
<< Instruction::MUL;
500
508
m_context << Instruction::NOT << Instruction::AND;
501
509
// stack: storage_ref cleared_value
502
- m_context << Instruction::SWAP1 << Instruction::SSTORE ;
510
+ m_context << Instruction::SWAP1 << s_storeInstruction ;
503
511
}
504
512
}
505
513
}
@@ -610,3 +618,6 @@ void TupleObject::setToZero(SourceLocation const&, bool) const
610
618
{
611
619
solAssert (false , " Tried to delete tuple." );
612
620
}
621
+
622
+ template class solidity ::frontend::GenericStorageItem<false >;
623
+ template class solidity ::frontend::GenericStorageItem<true >;
0 commit comments