Coverage Report

Created: 2025-09-08 08:10

/src/solidity/libsolidity/codegen/ExpressionCompiler.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * @author Christian <c@ethdev.com>
20
 * @date 2014
21
 * Solidity AST to EVM bytecode compiler for expressions.
22
 */
23
24
#include <libsolidity/codegen/ExpressionCompiler.h>
25
26
#include <libsolidity/codegen/ReturnInfo.h>
27
#include <libsolidity/codegen/CompilerContext.h>
28
#include <libsolidity/codegen/CompilerUtils.h>
29
#include <libsolidity/codegen/LValue.h>
30
31
#include <libsolidity/ast/AST.h>
32
#include <libsolidity/ast/ASTUtils.h>
33
#include <libsolidity/ast/TypeProvider.h>
34
35
#include <libevmasm/GasMeter.h>
36
#include <libsolutil/Common.h>
37
#include <libsolutil/FunctionSelector.h>
38
#include <libsolutil/Keccak256.h>
39
#include <libsolutil/Whiskers.h>
40
#include <libsolutil/StackTooDeepString.h>
41
42
#include <boost/algorithm/string/replace.hpp>
43
#include <numeric>
44
#include <utility>
45
46
using namespace solidity;
47
using namespace solidity::evmasm;
48
using namespace solidity::frontend;
49
using namespace solidity::langutil;
50
using namespace solidity::util;
51
52
namespace
53
{
54
55
Type const* closestType(Type const* _type, Type const* _targetType, bool _isShiftOp)
56
32.4k
{
57
32.4k
  if (_isShiftOp)
58
26
    return _type->mobileType();
59
32.4k
  else if (auto const* tupleType = dynamic_cast<TupleType const*>(_type))
60
471
  {
61
471
    solAssert(_targetType, "");
62
471
    TypePointers const& targetComponents = dynamic_cast<TupleType const&>(*_targetType).components();
63
471
    solAssert(tupleType->components().size() == targetComponents.size(), "");
64
471
    TypePointers tempComponents(targetComponents.size());
65
1.47k
    for (size_t i = 0; i < targetComponents.size(); ++i)
66
1.00k
    {
67
1.00k
      if (tupleType->components()[i] && targetComponents[i])
68
652
      {
69
652
        tempComponents[i] = closestType(tupleType->components()[i], targetComponents[i], _isShiftOp);
70
652
        solAssert(tempComponents[i], "");
71
652
      }
72
1.00k
    }
73
471
    return TypeProvider::tuple(std::move(tempComponents));
74
471
  }
75
31.9k
  else
76
31.9k
    return _targetType->dataStoredIn(DataLocation::Storage) ? _type->mobileType() : _targetType;
77
32.4k
}
78
79
}
80
81
void ExpressionCompiler::compile(Expression const& _expression)
82
157k
{
83
157k
  _expression.accept(*this);
84
157k
}
85
86
void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl)
87
1.68k
{
88
1.68k
  if (!_varDecl.value())
89
0
    return;
90
1.68k
  Type const* type = _varDecl.value()->annotation().type;
91
1.68k
  solAssert(!!type, "Type information not available.");
92
1.68k
  CompilerContext::LocationSetter locationSetter(m_context, _varDecl);
93
1.68k
  _varDecl.value()->accept(*this);
94
95
1.68k
  if (_varDecl.annotation().type->dataStoredIn(DataLocation::Storage))
96
773
  {
97
    // reference type, only convert value to mobile type and do final conversion in storeValue.
98
773
    auto mt = type->mobileType();
99
773
    solAssert(mt, "");
100
773
    utils().convertType(*type, *mt);
101
773
    type = mt;
102
773
  }
103
910
  else
104
910
  {
105
910
    utils().convertType(*type, *_varDecl.annotation().type);
106
910
    type = _varDecl.annotation().type;
107
910
  }
108
1.68k
  if (_varDecl.immutable())
109
127
    ImmutableItem(m_context, _varDecl).storeValue(*type, _varDecl.location(), true);
110
1.55k
  else
111
1.55k
  {
112
1.55k
    solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient);
113
1.55k
    StorageItem(m_context, _varDecl).storeValue(*type, _varDecl.location(), true);
114
1.55k
  }
115
1.68k
}
116
117
void ExpressionCompiler::appendConstStateVariableAccessor(VariableDeclaration const& _varDecl)
118
33
{
119
33
  solAssert(_varDecl.isConstant(), "");
120
33
  acceptAndConvert(*_varDecl.value(), *_varDecl.annotation().type);
121
122
  // append return
123
33
  m_context << dupInstruction(_varDecl.annotation().type->sizeOnStack() + 1);
124
33
  m_context.appendJump(evmasm::AssemblyItem::JumpType::OutOfFunction);
125
33
}
126
127
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
128
1.82k
{
129
1.82k
  solAssert(!_varDecl.isConstant(), "");
130
1.82k
  CompilerContext::LocationSetter locationSetter(m_context, _varDecl);
131
1.82k
  FunctionType accessorType(_varDecl);
132
133
1.82k
  TypePointers paramTypes = accessorType.parameterTypes();
134
1.82k
  if (_varDecl.immutable())
135
1.82k
    solAssert(paramTypes.empty(), "");
136
137
1.82k
  m_context.adjustStackOffset(static_cast<int>(1 + CompilerUtils::sizeOnStack(paramTypes)));
138
139
1.82k
  if (!_varDecl.immutable())
140
1.77k
  {
141
    // retrieve the position of the variable
142
1.77k
    auto const& location = m_context.storageLocationOfVariable(_varDecl);
143
1.77k
    m_context << location.first << u256(location.second);
144
1.77k
  }
145
146
1.82k
  Type const* returnType = _varDecl.annotation().type;
147
148
2.26k
  for (size_t i = 0; i < paramTypes.size(); ++i)
149
440
  {
150
440
    if (auto mappingType = dynamic_cast<MappingType const*>(returnType))
151
145
    {
152
145
      solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
153
145
      solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient);
154
155
      // pop offset
156
145
      m_context << Instruction::POP;
157
145
      if (paramTypes[i]->isDynamicallySized())
158
25
      {
159
25
        solAssert(
160
25
          dynamic_cast<ArrayType const&>(*paramTypes[i]).isByteArrayOrString(),
161
25
          "Expected string or byte array for mapping key type"
162
25
        );
163
164
        // stack: <keys..> <slot position>
165
166
        // copy key[i] to top.
167
25
        utils().copyToStackTop(static_cast<unsigned>(paramTypes.size() - i + 1), 1);
168
169
25
        m_context.appendInlineAssembly(R"({
170
25
          let key_len := mload(key_ptr)
171
25
          // Temp. use the memory after the array data for the slot
172
25
          // position
173
25
          let post_data_ptr := add(key_ptr, add(key_len, 0x20))
174
25
          let orig_data := mload(post_data_ptr)
175
25
          mstore(post_data_ptr, slot_pos)
176
25
          let hash := keccak256(add(key_ptr, 0x20), add(key_len, 0x20))
177
25
          mstore(post_data_ptr, orig_data)
178
25
          slot_pos := hash
179
25
        })", {"slot_pos", "key_ptr"});
180
181
25
        m_context << Instruction::POP;
182
25
      }
183
120
      else
184
120
      {
185
120
        solAssert(paramTypes[i]->isValueType(), "Expected value type for mapping key");
186
187
        // move storage offset to memory.
188
120
        utils().storeInMemory(32);
189
190
        // move key to memory.
191
120
        utils().copyToStackTop(static_cast<unsigned>(paramTypes.size() - i), 1);
192
120
        utils().storeInMemory(0);
193
120
        m_context << u256(64) << u256(0);
194
120
        m_context << Instruction::KECCAK256;
195
120
      }
196
197
      // push offset
198
145
      m_context << u256(0);
199
145
      returnType = mappingType->valueType();
200
145
    }
201
295
    else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
202
295
    {
203
295
      solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient);
204
205
      // pop offset
206
295
      m_context << Instruction::POP;
207
295
      utils().copyToStackTop(static_cast<unsigned>(paramTypes.size() - i + 1), 1);
208
209
295
      ArrayUtils(m_context).retrieveLength(*arrayType, 1);
210
      // Stack: ref [length] index length
211
      // check out-of-bounds access
212
295
      m_context << Instruction::DUP2 << Instruction::LT;
213
295
      auto tag = m_context.appendConditionalJump();
214
295
      m_context << u256(0) << Instruction::DUP1 << Instruction::REVERT;
215
295
      m_context << tag;
216
217
295
      ArrayUtils(m_context).accessIndex(*arrayType, false);
218
295
      returnType = arrayType->baseType();
219
295
    }
220
0
    else
221
295
      solAssert(false, "Index access is allowed only for \"mapping\" and \"array\" types.");
222
440
  }
223
  // remove index arguments.
224
1.82k
  if (paramTypes.size() == 1)
225
214
    m_context << Instruction::SWAP2 << Instruction::POP << Instruction::SWAP1;
226
1.61k
  else if (paramTypes.size() >= 2)
227
90
  {
228
90
    m_context << swapInstruction(static_cast<unsigned>(paramTypes.size()));
229
90
    m_context << Instruction::POP;
230
90
    m_context << swapInstruction(static_cast<unsigned>(paramTypes.size()));
231
90
    utils().popStackSlots(paramTypes.size() - 1);
232
90
  }
233
1.82k
  unsigned retSizeOnStack = 0;
234
1.82k
  auto returnTypes = accessorType.returnParameterTypes();
235
1.82k
  solAssert(returnTypes.size() >= 1, "");
236
1.82k
  if (StructType const* structType = dynamic_cast<StructType const*>(returnType))
237
78
  {
238
78
    solAssert(_varDecl.referenceLocation() != VariableDeclaration::Location::Transient);
239
78
    solAssert(!_varDecl.immutable(), "");
240
    // remove offset
241
78
    m_context << Instruction::POP;
242
78
    auto const& names = accessorType.returnParameterNames();
243
    // struct
244
226
    for (size_t i = 0; i < names.size(); ++i)
245
148
    {
246
148
      if (returnTypes[i]->category() == Type::Category::Mapping)
247
0
        continue;
248
148
      if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
249
49
        if (!arrayType->isByteArrayOrString())
250
0
          continue;
251
148
      std::pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
252
148
      m_context << Instruction::DUP1 << u256(offsets.first) << Instruction::ADD << u256(offsets.second);
253
148
      Type const* memberType = structType->memberType(names[i]);
254
148
      StorageItem(m_context, *memberType).retrieveValue(SourceLocation(), true);
255
148
      utils().convertType(*memberType, *returnTypes[i]);
256
148
      utils().moveToStackTop(returnTypes[i]->sizeOnStack());
257
148
      retSizeOnStack += returnTypes[i]->sizeOnStack();
258
148
    }
259
    // remove slot
260
78
    m_context << Instruction::POP;
261
78
  }
262
1.74k
  else
263
1.74k
  {
264
    // simple value or array
265
1.74k
    solAssert(returnTypes.size() == 1, "");
266
1.74k
    if (_varDecl.immutable())
267
51
      ImmutableItem(m_context, _varDecl).retrieveValue(SourceLocation());
268
1.69k
    else if (_varDecl.referenceLocation() == VariableDeclaration::Location::Transient)
269
0
      TransientStorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true);
270
1.69k
    else
271
1.69k
      StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true);
272
1.74k
    utils().convertType(*returnType, *returnTypes.front());
273
1.74k
    retSizeOnStack = returnTypes.front()->sizeOnStack();
274
1.74k
  }
275
1.82k
  solAssert(retSizeOnStack == utils().sizeOnStack(returnTypes), "");
276
1.82k
  if (retSizeOnStack > 15)
277
0
    BOOST_THROW_EXCEPTION(
278
1.82k
      StackTooDeepError() <<
279
1.82k
      errinfo_sourceLocation(_varDecl.location()) <<
280
1.82k
      util::errinfo_comment(util::stackTooDeepString)
281
1.82k
    );
282
1.82k
  m_context << dupInstruction(retSizeOnStack + 1);
283
1.82k
  m_context.appendJump(evmasm::AssemblyItem::JumpType::OutOfFunction);
284
1.82k
}
285
286
bool ExpressionCompiler::visit(Conditional const& _condition)
287
244
{
288
244
  CompilerContext::LocationSetter locationSetter(m_context, _condition);
289
244
  _condition.condition().accept(*this);
290
244
  evmasm::AssemblyItem trueTag = m_context.appendConditionalJump();
291
244
  acceptAndConvert(_condition.falseExpression(), *_condition.annotation().type);
292
244
  evmasm::AssemblyItem endTag = m_context.appendJumpToNew();
293
244
  m_context << trueTag;
294
244
  int offset = static_cast<int>(_condition.annotation().type->sizeOnStack());
295
244
  m_context.adjustStackOffset(-offset);
296
244
  acceptAndConvert(_condition.trueExpression(), *_condition.annotation().type);
297
244
  m_context << endTag;
298
244
  return false;
299
244
}
300
301
bool ExpressionCompiler::visit(Assignment const& _assignment)
302
31.8k
{
303
31.8k
  CompilerContext::LocationSetter locationSetter(m_context, _assignment);
304
31.8k
  Token op = _assignment.assignmentOperator();
305
31.8k
  Token binOp = op == Token::Assign ? op : TokenTraits::AssignmentToBinaryOp(op);
306
31.8k
  Type const& leftType = *_assignment.leftHandSide().annotation().type;
307
31.8k
  if (leftType.category() == Type::Category::Tuple)
308
455
  {
309
455
    solAssert(*_assignment.annotation().type == TupleType(), "");
310
455
    solAssert(op == Token::Assign, "");
311
455
  }
312
31.3k
  else
313
31.8k
    solAssert(*_assignment.annotation().type == leftType, "");
314
31.8k
  bool cleanupNeeded = false;
315
31.8k
  if (op != Token::Assign)
316
388
    cleanupNeeded = cleanupNeededForOp(leftType.category(), binOp, m_context.arithmetic());
317
31.8k
  _assignment.rightHandSide().accept(*this);
318
  // Perform some conversion already. This will convert storage types to memory and literals
319
  // to their actual type, but will not convert e.g. memory to storage.
320
31.8k
  Type const* rightIntermediateType = closestType(
321
31.8k
    _assignment.rightHandSide().annotation().type,
322
31.8k
    _assignment.leftHandSide().annotation().type,
323
31.8k
    op != Token::Assign && TokenTraits::isShiftOp(binOp)
324
31.8k
  );
325
326
31.8k
  solAssert(rightIntermediateType, "");
327
31.8k
  utils().convertType(*_assignment.rightHandSide().annotation().type, *rightIntermediateType, cleanupNeeded);
328
329
31.8k
  _assignment.leftHandSide().accept(*this);
330
31.8k
  solAssert(!!m_currentLValue, "LValue not retrieved.");
331
332
31.8k
  if (op == Token::Assign)
333
31.4k
    m_currentLValue->storeValue(*rightIntermediateType, _assignment.location());
334
391
  else  // compound assignment
335
391
  {
336
391
    solAssert(binOp != Token::Exp, "Compound exp is not possible.");
337
391
    solAssert(leftType.isValueType(), "Compound operators only available for value types.");
338
391
    unsigned lvalueSize = m_currentLValue->sizeOnStack();
339
391
    unsigned itemSize = _assignment.annotation().type->sizeOnStack();
340
391
    if (lvalueSize > 0)
341
177
    {
342
177
      utils().copyToStackTop(lvalueSize + itemSize, itemSize);
343
177
      utils().copyToStackTop(itemSize + lvalueSize, lvalueSize);
344
      // value lvalue_ref value lvalue_ref
345
177
    }
346
391
    m_currentLValue->retrieveValue(_assignment.location(), true);
347
391
    utils().convertType(leftType, leftType, cleanupNeeded);
348
349
391
    if (TokenTraits::isShiftOp(binOp))
350
26
      appendShiftOperatorCode(binOp, leftType, *rightIntermediateType);
351
365
    else
352
365
    {
353
365
      solAssert(leftType == *rightIntermediateType, "");
354
365
      appendOrdinaryBinaryOperatorCode(binOp, leftType);
355
365
    }
356
391
    if (lvalueSize > 0)
357
177
    {
358
177
      if (itemSize + lvalueSize > 16)
359
0
        BOOST_THROW_EXCEPTION(
360
177
          StackTooDeepError() <<
361
177
          errinfo_sourceLocation(_assignment.location()) <<
362
177
          util::errinfo_comment(util::stackTooDeepString)
363
177
        );
364
      // value [lvalue_ref] updated_value
365
354
      for (unsigned i = 0; i < itemSize; ++i)
366
177
        m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP;
367
177
    }
368
391
    m_currentLValue->storeValue(*_assignment.annotation().type, _assignment.location());
369
391
  }
370
31.8k
  m_currentLValue.reset();
371
31.8k
  return false;
372
31.8k
}
373
374
bool ExpressionCompiler::visit(TupleExpression const& _tuple)
375
4.20k
{
376
4.20k
  if (_tuple.isInlineArray())
377
467
  {
378
467
    ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
379
380
467
    solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
381
467
    utils().allocateMemory(std::max(u256(32u), arrayType.memoryDataSize()));
382
467
    m_context << Instruction::DUP1;
383
384
467
    for (auto const& component: _tuple.components())
385
1.61k
    {
386
1.61k
      acceptAndConvert(*component, *arrayType.baseType(), true);
387
1.61k
      utils().storeInMemoryDynamic(*arrayType.baseType(), true);
388
1.61k
    }
389
390
467
    m_context << Instruction::POP;
391
467
  }
392
3.73k
  else
393
3.73k
  {
394
3.73k
    std::vector<std::unique_ptr<LValue>> lvalues;
395
3.73k
    for (auto const& component: _tuple.components())
396
6.34k
      if (component)
397
5.99k
      {
398
5.99k
        component->accept(*this);
399
5.99k
        if (_tuple.annotation().willBeWrittenTo)
400
806
        {
401
806
          solAssert(!!m_currentLValue, "");
402
806
          lvalues.push_back(std::move(m_currentLValue));
403
806
        }
404
5.99k
      }
405
348
      else if (_tuple.annotation().willBeWrittenTo)
406
348
        lvalues.push_back(std::unique_ptr<LValue>());
407
3.73k
    if (_tuple.annotation().willBeWrittenTo)
408
625
    {
409
625
      if (_tuple.components().size() == 1)
410
154
        m_currentLValue = std::move(lvalues[0]);
411
471
      else
412
471
        m_currentLValue = std::make_unique<TupleObject>(m_context, std::move(lvalues));
413
625
    }
414
3.73k
  }
415
4.20k
  return false;
416
4.20k
}
417
418
bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
419
17.8k
{
420
17.8k
  CompilerContext::LocationSetter locationSetter(m_context, _unaryOperation);
421
422
17.8k
  FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction;
423
17.8k
  if (function)
424
13
  {
425
13
    solAssert(function->isFree());
426
427
13
    FunctionType const* functionType = _unaryOperation.userDefinedFunctionType();
428
13
    solAssert(functionType);
429
13
    solAssert(functionType->parameterTypes().size() == 1);
430
13
    solAssert(functionType->returnParameterTypes().size() == 1);
431
13
    solAssert(functionType->kind() == FunctionType::Kind::Internal);
432
433
13
    evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
434
13
    acceptAndConvert(
435
13
      _unaryOperation.subExpression(),
436
13
      *functionType->parameterTypes()[0],
437
13
      false // _cleanupNeeded
438
13
    );
439
440
13
    m_context << m_context.functionEntryLabel(*function).pushTag();
441
13
    m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
442
13
    m_context << returnLabel;
443
444
13
    unsigned parameterSize = CompilerUtils::sizeOnStack(functionType->parameterTypes());
445
13
    unsigned returnParametersSize = CompilerUtils::sizeOnStack(functionType->returnParameterTypes());
446
447
    // callee adds return parameters, but removes arguments and return label
448
13
    m_context.adjustStackOffset(static_cast<int>(returnParametersSize) - static_cast<int>(parameterSize) - 1);
449
450
13
    return false;
451
13
  }
452
453
17.8k
  Type const& type = *_unaryOperation.annotation().type;
454
17.8k
  if (type.category() == Type::Category::RationalNumber)
455
4.54k
  {
456
4.54k
    m_context << type.literalValue(nullptr);
457
4.54k
    return false;
458
4.54k
  }
459
460
13.2k
  _unaryOperation.subExpression().accept(*this);
461
462
13.2k
  switch (_unaryOperation.getOperator())
463
13.2k
  {
464
8.32k
  case Token::Not: // !
465
8.32k
    m_context << Instruction::ISZERO;
466
8.32k
    break;
467
698
  case Token::BitNot: // ~
468
698
    m_context << Instruction::NOT;
469
698
    break;
470
155
  case Token::Delete: // delete
471
155
    solAssert(!!m_currentLValue, "LValue not retrieved.");
472
155
    m_currentLValue->setToZero(_unaryOperation.location());
473
155
    m_currentLValue.reset();
474
155
    break;
475
3.86k
  case Token::Inc: // ++ (pre- or postfix)
476
3.97k
  case Token::Dec: // -- (pre- or postfix)
477
3.97k
    solAssert(!!m_currentLValue, "LValue not retrieved.");
478
3.97k
    solUnimplementedAssert(
479
3.97k
      type.category() != Type::Category::FixedPoint,
480
3.97k
      "Not yet implemented - FixedPointType."
481
3.97k
    );
482
3.97k
    m_currentLValue->retrieveValue(_unaryOperation.location());
483
3.97k
    if (!_unaryOperation.isPrefixOperation())
484
3.60k
    {
485
      // store value for later
486
3.60k
      solUnimplementedAssert(type.sizeOnStack() == 1, "Stack size != 1 not implemented.");
487
3.60k
      m_context << Instruction::DUP1;
488
3.60k
      if (m_currentLValue->sizeOnStack() > 0)
489
333
        for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i)
490
246
          m_context << swapInstruction(i);
491
3.60k
    }
492
3.97k
    if (_unaryOperation.getOperator() == Token::Inc)
493
3.86k
    {
494
3.86k
      if (m_context.arithmetic() == Arithmetic::Checked)
495
522
        m_context.callYulFunction(m_context.utilFunctions().incrementCheckedFunction(type), 1, 1);
496
3.34k
      else
497
3.34k
      {
498
3.34k
        m_context << u256(1);
499
3.34k
        m_context << Instruction::ADD;
500
3.34k
      }
501
3.86k
    }
502
114
    else
503
114
    {
504
114
      if (m_context.arithmetic() == Arithmetic::Checked)
505
108
        m_context.callYulFunction(m_context.utilFunctions().decrementCheckedFunction(type), 1, 1);
506
6
      else
507
6
      {
508
6
        m_context << u256(1);
509
6
        m_context << Instruction::SWAP1 << Instruction::SUB;
510
6
      }
511
114
    }
512
    // Stack for prefix: [ref...] (*ref)+-1
513
    // Stack for postfix: *ref [ref...] (*ref)+-1
514
4.36k
    for (unsigned i = m_currentLValue->sizeOnStack(); i > 0; --i)
515
385
      m_context << swapInstruction(i);
516
3.97k
    m_currentLValue->storeValue(
517
3.97k
      *_unaryOperation.annotation().type, _unaryOperation.location(),
518
3.97k
      !_unaryOperation.isPrefixOperation());
519
3.97k
    m_currentLValue.reset();
520
3.97k
    break;
521
0
  case Token::Add: // +
522
    // According to SyntaxChecker...
523
0
    solAssert(false, "Use of unary + is disallowed.");
524
59
  case Token::Sub: // -
525
59
    solUnimplementedAssert(
526
59
      type.category() != Type::Category::FixedPoint,
527
59
      "Not yet implemented - FixedPointType."
528
59
    );
529
59
    if (m_context.arithmetic() == Arithmetic::Checked)
530
46
      m_context.callYulFunction(m_context.utilFunctions().negateNumberCheckedFunction(type), 1, 1);
531
13
    else
532
13
      m_context << u256(0) << Instruction::SUB;
533
59
    break;
534
0
  default:
535
0
    solAssert(false, "Invalid unary operator: " + std::string(TokenTraits::toString(_unaryOperation.getOperator())));
536
13.2k
  }
537
13.2k
  return false;
538
13.2k
}
539
540
bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
541
54.8k
{
542
54.8k
  CompilerContext::LocationSetter locationSetter(m_context, _binaryOperation);
543
54.8k
  Expression const& leftExpression = _binaryOperation.leftExpression();
544
54.8k
  Expression const& rightExpression = _binaryOperation.rightExpression();
545
54.8k
  FunctionDefinition const* function = *_binaryOperation.annotation().userDefinedFunction;
546
54.8k
  if (function)
547
33
  {
548
33
    solAssert(function->isFree());
549
550
33
    FunctionType const* functionType = _binaryOperation.userDefinedFunctionType();
551
33
    solAssert(functionType);
552
33
    solAssert(functionType->parameterTypes().size() == 2);
553
33
    solAssert(functionType->returnParameterTypes().size() == 1);
554
33
    solAssert(functionType->kind() == FunctionType::Kind::Internal);
555
556
33
    evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
557
33
    acceptAndConvert(
558
33
      leftExpression,
559
33
      *functionType->parameterTypes()[0],
560
33
      false // _cleanupNeeded
561
33
    );
562
33
    acceptAndConvert(
563
33
      rightExpression,
564
33
      *functionType->parameterTypes()[1],
565
33
      false // _cleanupNeeded
566
33
    );
567
568
33
    m_context << m_context.functionEntryLabel(*function).pushTag();
569
33
    m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
570
33
    m_context << returnLabel;
571
572
33
    unsigned parameterSize = CompilerUtils::sizeOnStack(functionType->parameterTypes());
573
33
    unsigned returnParametersSize = CompilerUtils::sizeOnStack(functionType->returnParameterTypes());
574
575
    // callee adds return parameters, but removes arguments and return label
576
33
    m_context.adjustStackOffset(static_cast<int>(returnParametersSize) - static_cast<int>(parameterSize) - 1);
577
33
    return false;
578
33
  }
579
580
54.8k
  solAssert(!!_binaryOperation.annotation().commonType);
581
54.8k
  Type const* commonType = _binaryOperation.annotation().commonType;
582
54.8k
  Token const c_op = _binaryOperation.getOperator();
583
584
54.8k
  if (c_op == Token::And || c_op == Token::Or) // special case: short-circuiting
585
592
    appendAndOrOperatorCode(_binaryOperation);
586
54.2k
  else if (commonType->category() == Type::Category::RationalNumber)
587
1.70k
    m_context << commonType->literalValue(nullptr);
588
52.5k
  else
589
52.5k
  {
590
52.5k
    bool cleanupNeeded = cleanupNeededForOp(commonType->category(), c_op, m_context.arithmetic());
591
592
52.5k
    Type const* leftTargetType = commonType;
593
52.5k
    Type const* rightTargetType =
594
52.5k
      TokenTraits::isShiftOp(c_op) || c_op == Token::Exp ?
595
700
      rightExpression.annotation().type->mobileType() :
596
52.5k
      commonType;
597
52.5k
    solAssert(rightTargetType, "");
598
599
    // for commutative operators, push the literal as late as possible to allow improved optimization
600
52.5k
    auto isLiteral = [](Expression const& _e)
601
52.5k
    {
602
1.27k
      return dynamic_cast<Literal const*>(&_e) || _e.annotation().type->category() == Type::Category::RationalNumber;
603
1.27k
    };
604
52.5k
    bool swap = m_optimiseOrderLiterals && TokenTraits::isCommutativeOp(c_op) && isLiteral(rightExpression) && !isLiteral(leftExpression);
605
52.5k
    if (swap)
606
492
    {
607
492
      acceptAndConvert(leftExpression, *leftTargetType, cleanupNeeded);
608
492
      acceptAndConvert(rightExpression, *rightTargetType, cleanupNeeded);
609
492
    }
610
52.0k
    else
611
52.0k
    {
612
52.0k
      acceptAndConvert(rightExpression, *rightTargetType, cleanupNeeded);
613
52.0k
      acceptAndConvert(leftExpression, *leftTargetType, cleanupNeeded);
614
52.0k
    }
615
52.5k
    if (TokenTraits::isShiftOp(c_op))
616
      // shift only cares about the signedness of both sides
617
83
      appendShiftOperatorCode(c_op, *leftTargetType, *rightTargetType);
618
52.4k
    else if (c_op == Token::Exp)
619
617
      appendExpOperatorCode(*leftTargetType, *rightTargetType);
620
51.8k
    else if (TokenTraits::isCompareOp(c_op))
621
44.9k
      appendCompareOperatorCode(c_op, *commonType);
622
6.90k
    else
623
6.90k
      appendOrdinaryBinaryOperatorCode(c_op, *commonType);
624
52.5k
  }
625
626
  // do not visit the child nodes, we already did that explicitly
627
54.8k
  return false;
628
54.8k
}
629
630
bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
631
34.0k
{
632
34.0k
  auto functionCallKind = *_functionCall.annotation().kind;
633
634
34.0k
  CompilerContext::LocationSetter locationSetter(m_context, _functionCall);
635
34.0k
  if (functionCallKind == FunctionCallKind::TypeConversion)
636
9.65k
  {
637
9.65k
    solAssert(_functionCall.arguments().size() == 1, "");
638
9.65k
    solAssert(_functionCall.names().empty(), "");
639
9.65k
    auto const& expression = *_functionCall.arguments().front();
640
9.65k
    auto const& targetType = *_functionCall.annotation().type;
641
9.65k
    if (auto const* typeType = dynamic_cast<TypeType const*>(expression.annotation().type))
642
9
      if (auto const* addressType = dynamic_cast<AddressType const*>(&targetType))
643
9
      {
644
9
        auto const* contractType = dynamic_cast<ContractType const*>(typeType->actualType());
645
9
        solAssert(
646
9
          contractType &&
647
9
          contractType->contractDefinition().isLibrary() &&
648
9
          addressType->stateMutability() == StateMutability::NonPayable,
649
9
          ""
650
9
        );
651
9
        m_context.appendLibraryAddress(contractType->contractDefinition().fullyQualifiedName());
652
9
        return false;
653
9
      }
654
9.64k
    acceptAndConvert(expression, targetType);
655
9.64k
    return false;
656
9.65k
  }
657
658
24.4k
  FunctionTypePointer functionType;
659
24.4k
  if (functionCallKind == FunctionCallKind::StructConstructorCall)
660
127
  {
661
127
    auto const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
662
127
    auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
663
127
    functionType = structType.constructorType();
664
127
  }
665
24.2k
  else
666
24.2k
    functionType = dynamic_cast<FunctionType const*>(_functionCall.expression().annotation().type);
667
668
24.4k
  TypePointers parameterTypes = functionType->parameterTypes();
669
670
24.4k
  std::vector<ASTPointer<Expression const>> const& arguments = _functionCall.sortedArguments();
671
672
24.4k
  if (functionCallKind == FunctionCallKind::StructConstructorCall)
673
127
  {
674
127
    TypeType const& type = dynamic_cast<TypeType const&>(*_functionCall.expression().annotation().type);
675
127
    auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
676
677
127
    utils().allocateMemory(std::max(u256(32u), structType.memoryDataSize()));
678
127
    m_context << Instruction::DUP1;
679
680
330
    for (unsigned i = 0; i < arguments.size(); ++i)
681
203
    {
682
203
      acceptAndConvert(*arguments[i], *functionType->parameterTypes()[i]);
683
203
      utils().storeInMemoryDynamic(*functionType->parameterTypes()[i]);
684
203
    }
685
127
    m_context << Instruction::POP;
686
127
  }
687
24.2k
  else
688
24.2k
  {
689
24.2k
    FunctionType const& function = *functionType;
690
24.2k
    if (function.hasBoundFirstArgument())
691
24.2k
      solAssert(
692
24.2k
        function.kind() == FunctionType::Kind::DelegateCall ||
693
24.2k
        function.kind() == FunctionType::Kind::Internal ||
694
24.2k
        function.kind() == FunctionType::Kind::ArrayPush ||
695
24.2k
        function.kind() == FunctionType::Kind::ArrayPop,
696
24.2k
      "");
697
24.2k
    switch (function.kind())
698
24.2k
    {
699
0
    case FunctionType::Kind::Declaration:
700
0
      solAssert(false, "Attempted to generate code for calling a function definition.");
701
0
      break;
702
10.7k
    case FunctionType::Kind::Internal:
703
10.7k
    {
704
      // Calling convention: Caller pushes return address and arguments
705
      // Callee removes them and pushes return values
706
707
10.7k
      evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
708
30.8k
      for (unsigned i = 0; i < arguments.size(); ++i)
709
20.1k
        acceptAndConvert(*arguments[i], *function.parameterTypes()[i]);
710
10.7k
      _functionCall.expression().accept(*this);
711
712
10.7k
      unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes());
713
10.7k
      if (function.hasBoundFirstArgument())
714
113
      {
715
        // stack: arg2, ..., argn, label, arg1
716
113
        unsigned depth = parameterSize + 1;
717
113
        utils().moveIntoStack(depth, function.selfType()->sizeOnStack());
718
113
        parameterSize += function.selfType()->sizeOnStack();
719
113
      }
720
721
10.7k
      if (m_context.runtimeContext())
722
        // We have a runtime context, so we need the creation part.
723
209
        utils().rightShiftNumberOnStack(32);
724
10.5k
      else
725
        // Extract the runtime part.
726
10.5k
        m_context << ((u256(1) << 32) - 1) << Instruction::AND;
727
728
10.7k
      m_context.appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
729
10.7k
      m_context << returnLabel;
730
731
10.7k
      unsigned returnParametersSize = CompilerUtils::sizeOnStack(function.returnParameterTypes());
732
      // callee adds return parameters, but removes arguments and return label
733
10.7k
      m_context.adjustStackOffset(static_cast<int>(returnParametersSize) - static_cast<int>(parameterSize) - 1);
734
10.7k
      break;
735
0
    }
736
731
    case FunctionType::Kind::BareCall:
737
741
    case FunctionType::Kind::BareDelegateCall:
738
755
    case FunctionType::Kind::BareStaticCall:
739
755
      solAssert(!_functionCall.annotation().tryCall, "");
740
755
      [[fallthrough]];
741
3.13k
    case FunctionType::Kind::External:
742
3.27k
    case FunctionType::Kind::DelegateCall:
743
3.27k
      _functionCall.expression().accept(*this);
744
3.27k
      appendExternalFunctionCall(function, arguments, _functionCall.annotation().tryCall);
745
3.27k
      break;
746
0
    case FunctionType::Kind::BareCallCode:
747
0
      solAssert(false, "Callcode has been removed.");
748
202
    case FunctionType::Kind::Creation:
749
202
    {
750
202
      _functionCall.expression().accept(*this);
751
      // Stack: [salt], [value]
752
753
202
      solAssert(!function.gasSet(), "Gas limit set for contract creation.");
754
202
      solAssert(function.returnParameterTypes().size() == 1, "");
755
202
      TypePointers argumentTypes;
756
202
      for (auto const& arg: arguments)
757
20
      {
758
20
        arg->accept(*this);
759
20
        argumentTypes.push_back(arg->annotation().type);
760
20
      }
761
202
      ContractDefinition const* contract =
762
202
        &dynamic_cast<ContractType const&>(*function.returnParameterTypes().front()).contractDefinition();
763
202
      utils().fetchFreeMemoryPointer();
764
202
      utils().copyContractCodeToMemory(*contract, true);
765
202
      utils().abiEncode(argumentTypes, function.parameterTypes());
766
      // now on stack: [salt], [value], memory_end_ptr
767
      // need: [salt], size, offset, value
768
769
202
      if (function.saltSet())
770
12
      {
771
12
        m_context << dupInstruction(2 + (function.valueSet() ? 1 : 0));
772
12
        m_context << Instruction::SWAP1;
773
12
      }
774
775
      // now: [salt], [value], [salt], memory_end_ptr
776
202
      utils().toSizeAfterFreeMemoryPointer();
777
778
      // now: [salt], [value], [salt], size, offset
779
202
      if (function.valueSet())
780
39
        m_context << dupInstruction(3 + (function.saltSet() ? 1 : 0));
781
163
      else
782
163
        m_context << u256(0);
783
784
      // now: [salt], [value], [salt], size, offset, value
785
202
      if (function.saltSet())
786
12
        m_context << Instruction::CREATE2;
787
190
      else
788
190
        m_context << Instruction::CREATE;
789
790
      // now: [salt], [value], address
791
792
202
      if (function.valueSet())
793
39
        m_context << swapInstruction(1) << Instruction::POP;
794
202
      if (function.saltSet())
795
12
        m_context << swapInstruction(1) << Instruction::POP;
796
797
      // Check if zero (reverted)
798
202
      m_context << Instruction::DUP1 << Instruction::ISZERO;
799
202
      if (_functionCall.annotation().tryCall)
800
5
      {
801
        // If this is a try call, return "<address> 1" in the success case and
802
        // "0" in the error case.
803
5
        AssemblyItem errorCase = m_context.appendConditionalJump();
804
5
        m_context << u256(1);
805
5
        m_context << errorCase;
806
5
      }
807
197
      else
808
197
        m_context.appendConditionalRevert(true);
809
202
      break;
810
202
    }
811
0
    case FunctionType::Kind::SetGas:
812
0
    {
813
      // stack layout: contract_address function_id [gas] [value]
814
0
      _functionCall.expression().accept(*this);
815
816
0
      acceptAndConvert(*arguments.front(), *TypeProvider::uint256(), true);
817
      // Note that function is not the original function, but the ".gas" function.
818
      // Its values of gasSet and valueSet is equal to the original function's though.
819
0
      unsigned stackDepth = (function.gasSet() ? 1u : 0u) + (function.valueSet() ? 1u : 0u);
820
0
      if (stackDepth > 0)
821
0
        m_context << swapInstruction(stackDepth);
822
0
      if (function.gasSet())
823
0
        m_context << Instruction::POP;
824
0
      break;
825
202
    }
826
0
    case FunctionType::Kind::SetValue:
827
      // stack layout: contract_address function_id [gas] [value]
828
0
      _functionCall.expression().accept(*this);
829
      // Note that function is not the original function, but the ".value" function.
830
      // Its values of gasSet and valueSet is equal to the original function's though.
831
0
      if (function.valueSet())
832
0
        m_context << Instruction::POP;
833
0
      arguments.front()->accept(*this);
834
0
      break;
835
15
    case FunctionType::Kind::Send:
836
62
    case FunctionType::Kind::Transfer:
837
62
    {
838
62
      _functionCall.expression().accept(*this);
839
      // Provide the gas stipend manually at first because we may send zero ether.
840
      // Will be zeroed if we send more than zero ether.
841
62
      m_context << u256(evmasm::GasCosts::callStipend);
842
62
      acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true);
843
      // gas <- gas * !value
844
62
      m_context << Instruction::SWAP1 << Instruction::DUP2;
845
62
      m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1;
846
62
      FunctionType::Options callOptions;
847
62
      callOptions.valueSet = true;
848
62
      callOptions.gasSet = true;
849
62
      appendExternalFunctionCall(
850
62
        FunctionType(
851
62
          TypePointers{},
852
62
          TypePointers{},
853
62
          strings(),
854
62
          strings(),
855
62
          FunctionType::Kind::BareCall,
856
62
          StateMutability::NonPayable,
857
62
          nullptr,
858
62
          callOptions
859
62
        ),
860
62
        {},
861
62
        false
862
62
      );
863
62
      if (function.kind() == FunctionType::Kind::Transfer)
864
47
      {
865
        // Check if zero (out of stack or not enough balance).
866
47
        m_context << Instruction::ISZERO;
867
        // Revert message bubbles up.
868
47
        m_context.appendConditionalRevert(true);
869
47
      }
870
62
      break;
871
15
    }
872
6
    case FunctionType::Kind::Selfdestruct:
873
6
      acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true);
874
6
      m_context << Instruction::SELFDESTRUCT;
875
6
      break;
876
93
    case FunctionType::Kind::Revert:
877
93
    {
878
93
      if (arguments.empty())
879
65
        m_context.appendRevert();
880
28
      else
881
28
      {
882
        // function-sel(Error(string)) + encoding
883
28
        solAssert(arguments.size() == 1, "");
884
28
        solAssert(function.parameterTypes().size() == 1, "");
885
28
        if (m_context.revertStrings() == RevertStrings::Strip)
886
0
        {
887
0
          if (!*arguments.front()->annotation().isPure)
888
0
          {
889
0
            arguments.front()->accept(*this);
890
0
            utils().popStackElement(*arguments.front()->annotation().type);
891
0
          }
892
0
          m_context.appendRevert();
893
0
        }
894
28
        else
895
28
        {
896
28
          arguments.front()->accept(*this);
897
28
          utils().revertWithStringData(*arguments.front()->annotation().type);
898
28
        }
899
28
      }
900
93
      break;
901
93
    }
902
102
    case FunctionType::Kind::KECCAK256:
903
102
    {
904
102
      solAssert(arguments.size() == 1, "");
905
102
      solAssert(!function.padArguments(), "");
906
102
      Type const* argType = arguments.front()->annotation().type;
907
102
      solAssert(argType, "");
908
102
      arguments.front()->accept(*this);
909
102
      if (auto const* stringLiteral = dynamic_cast<StringLiteralType const*>(argType))
910
        // Optimization: Compute keccak256 on string literals at compile-time.
911
20
        m_context << u256(keccak256(stringLiteral->value()));
912
82
      else if (*argType == *TypeProvider::bytesMemory() || *argType == *TypeProvider::stringMemory())
913
73
      {
914
        // Optimization: If type is bytes or string, then do not encode,
915
        // but directly compute keccak256 on memory.
916
73
        ArrayUtils(m_context).retrieveLength(*TypeProvider::bytesMemory());
917
73
        m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD;
918
73
        m_context << Instruction::KECCAK256;
919
73
      }
920
9
      else
921
9
      {
922
9
        utils().fetchFreeMemoryPointer();
923
9
        utils().packedEncode({argType}, TypePointers());
924
9
        utils().toSizeAfterFreeMemoryPointer();
925
9
        m_context << Instruction::KECCAK256;
926
9
      }
927
102
      break;
928
102
    }
929
487
    case FunctionType::Kind::Event:
930
487
    {
931
487
      _functionCall.expression().accept(*this);
932
487
      auto const& event = dynamic_cast<EventDefinition const&>(function.declaration());
933
487
      unsigned numIndexed = 0;
934
487
      TypePointers paramTypes = function.parameterTypes();
935
      // All indexed arguments go to the stack
936
1.20k
      for (size_t arg = arguments.size(); arg > 0; --arg)
937
715
        if (event.parameters()[arg - 1]->isIndexed())
938
80
        {
939
80
          ++numIndexed;
940
80
          arguments[arg - 1]->accept(*this);
941
80
          if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[arg - 1]))
942
29
          {
943
29
            utils().fetchFreeMemoryPointer();
944
29
            utils().packedEncode(
945
29
              {arguments[arg - 1]->annotation().type},
946
29
              {referenceType}
947
29
            );
948
29
            utils().toSizeAfterFreeMemoryPointer();
949
29
            m_context << Instruction::KECCAK256;
950
29
          }
951
51
          else
952
51
          {
953
51
            solAssert(paramTypes[arg - 1]->isValueType(), "");
954
51
            if (auto functionType = dynamic_cast<FunctionType const*>(paramTypes[arg - 1]))
955
7
            {
956
7
              auto argumentType =
957
7
                dynamic_cast<FunctionType const*>(arguments[arg-1]->annotation().type);
958
7
              solAssert(
959
7
                argumentType &&
960
7
                functionType->kind() == FunctionType::Kind::External &&
961
7
                argumentType->kind() == FunctionType::Kind::External &&
962
7
                !argumentType->hasBoundFirstArgument(),
963
7
                ""
964
7
              );
965
966
7
              utils().combineExternalFunctionType(true);
967
7
            }
968
44
            else
969
44
              utils().convertType(
970
44
                *arguments[arg - 1]->annotation().type,
971
44
                *paramTypes[arg - 1],
972
44
                true
973
44
              );
974
51
          }
975
80
        }
976
487
      if (!event.isAnonymous())
977
483
      {
978
483
        m_context << u256(h256::Arith(keccak256(function.externalSignature())));
979
483
        ++numIndexed;
980
483
      }
981
487
      solAssert(numIndexed <= 4, "Too many indexed arguments.");
982
      // Copy all non-indexed arguments to memory (data)
983
      // Memory position is only a hack and should be removed once we have free memory pointer.
984
487
      TypePointers nonIndexedArgTypes;
985
487
      TypePointers nonIndexedParamTypes;
986
1.20k
      for (unsigned arg = 0; arg < arguments.size(); ++arg)
987
715
        if (!event.parameters()[arg]->isIndexed())
988
635
        {
989
635
          arguments[arg]->accept(*this);
990
635
          nonIndexedArgTypes.push_back(arguments[arg]->annotation().type);
991
635
          nonIndexedParamTypes.push_back(paramTypes[arg]);
992
635
        }
993
487
      utils().fetchFreeMemoryPointer();
994
487
      utils().abiEncode(nonIndexedArgTypes, nonIndexedParamTypes);
995
      // need: topic1 ... topicn memsize memstart
996
487
      utils().toSizeAfterFreeMemoryPointer();
997
487
      m_context << logInstruction(numIndexed);
998
487
      break;
999
487
    }
1000
51
    case FunctionType::Kind::Error:
1001
51
    {
1002
      // This case is part of the ``revert <error>`` path of the codegen.
1003
      // For ``require(bool, <error>)`` refer to the ``Kind::Require`` case.
1004
51
      _functionCall.expression().accept(*this);
1005
51
      std::vector<Type const*> argumentTypes;
1006
51
      for (ASTPointer<Expression const> const& arg: _functionCall.sortedArguments())
1007
48
      {
1008
48
        arg->accept(*this);
1009
48
        argumentTypes.push_back(arg->annotation().type);
1010
48
      }
1011
51
      solAssert(dynamic_cast<ErrorDefinition const*>(&function.declaration()), "");
1012
51
      utils().revertWithError(
1013
51
        function.externalSignature(),
1014
51
        function.parameterTypes(),
1015
51
        argumentTypes
1016
51
      );
1017
51
      break;
1018
51
    }
1019
162
    case FunctionType::Kind::Wrap:
1020
250
    case FunctionType::Kind::Unwrap:
1021
250
    {
1022
250
      solAssert(arguments.size() == 1, "");
1023
250
      Type const* argumentType = arguments.at(0)->annotation().type;
1024
250
      Type const* functionCallType = _functionCall.annotation().type;
1025
250
      solAssert(argumentType, "");
1026
250
      solAssert(functionCallType, "");
1027
250
      FunctionType::Kind kind = functionType->kind();
1028
250
      if (kind == FunctionType::Kind::Wrap)
1029
162
      {
1030
162
        solAssert(
1031
162
          argumentType->isImplicitlyConvertibleTo(
1032
162
            dynamic_cast<UserDefinedValueType const&>(*functionCallType).underlyingType()
1033
162
          ),
1034
162
          ""
1035
162
        );
1036
162
        solAssert(argumentType->isImplicitlyConvertibleTo(*function.parameterTypes()[0]), "");
1037
162
      }
1038
88
      else
1039
250
        solAssert(
1040
250
          dynamic_cast<UserDefinedValueType const&>(*argumentType) ==
1041
250
          dynamic_cast<UserDefinedValueType const&>(*function.parameterTypes()[0]),
1042
250
          ""
1043
250
        );
1044
1045
250
      acceptAndConvert(*arguments[0], *function.parameterTypes()[0]);
1046
250
      break;
1047
250
    }
1048
28
    case FunctionType::Kind::BlockHash:
1049
30
    case FunctionType::Kind::BlobHash:
1050
30
    {
1051
30
      acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true);
1052
30
      if (function.kind() == FunctionType::Kind::BlockHash)
1053
28
        m_context << Instruction::BLOCKHASH;
1054
2
      else
1055
2
        m_context << Instruction::BLOBHASH;
1056
30
      break;
1057
28
    }
1058
35
    case FunctionType::Kind::AddMod:
1059
50
    case FunctionType::Kind::MulMod:
1060
50
    {
1061
50
      acceptAndConvert(*arguments[2], *TypeProvider::uint256());
1062
50
      m_context << Instruction::DUP1 << Instruction::ISZERO;
1063
50
      m_context.appendConditionalPanic(util::PanicCode::DivisionByZero);
1064
150
      for (unsigned i = 1; i < 3; i ++)
1065
100
        acceptAndConvert(*arguments[2 - i], *TypeProvider::uint256());
1066
50
      if (function.kind() == FunctionType::Kind::AddMod)
1067
35
        m_context << Instruction::ADDMOD;
1068
15
      else
1069
15
        m_context << Instruction::MULMOD;
1070
50
      break;
1071
35
    }
1072
10
    case FunctionType::Kind::ECRecover:
1073
23
    case FunctionType::Kind::SHA256:
1074
62
    case FunctionType::Kind::RIPEMD160:
1075
62
    {
1076
62
      _functionCall.expression().accept(*this);
1077
62
      static std::map<FunctionType::Kind, u256> const contractAddresses{
1078
62
        {FunctionType::Kind::ECRecover, 1},
1079
62
        {FunctionType::Kind::SHA256, 2},
1080
62
        {FunctionType::Kind::RIPEMD160, 3}
1081
62
      };
1082
62
      m_context << contractAddresses.at(function.kind());
1083
62
      for (unsigned i = function.sizeOnStack(); i > 0; --i)
1084
0
        m_context << swapInstruction(i);
1085
62
      solAssert(!_functionCall.annotation().tryCall, "");
1086
62
      appendExternalFunctionCall(function, arguments, false);
1087
62
      break;
1088
62
    }
1089
3.04k
    case FunctionType::Kind::ArrayPush:
1090
3.04k
    {
1091
3.04k
      solAssert(function.hasBoundFirstArgument(), "");
1092
3.04k
      _functionCall.expression().accept(*this);
1093
1094
3.04k
      if (function.parameterTypes().size() == 0)
1095
2.68k
      {
1096
2.68k
        auto paramType = function.returnParameterTypes().at(0);
1097
2.68k
        solAssert(paramType, "");
1098
1099
2.68k
        ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
1100
2.68k
        solAssert(arrayType, "");
1101
1102
        // stack: ArrayReference
1103
2.68k
        m_context << u256(1) << Instruction::DUP2;
1104
2.68k
        ArrayUtils(m_context).incrementDynamicArraySize(*arrayType);
1105
        // stack: ArrayReference 1 newLength
1106
2.68k
        m_context << Instruction::SUB;
1107
        // stack: ArrayReference (newLength-1)
1108
2.68k
        ArrayUtils(m_context).accessIndex(*arrayType, false);
1109
1110
2.68k
        if (arrayType->isByteArrayOrString())
1111
12
          setLValue<StorageByteArrayElement>(_functionCall);
1112
2.67k
        else
1113
2.67k
          setLValueToStorageItem(_functionCall);
1114
2.68k
      }
1115
360
      else
1116
360
      {
1117
360
        solAssert(function.parameterTypes().size() == 1, "");
1118
360
        solAssert(!!function.parameterTypes()[0], "");
1119
360
        Type const* paramType = function.parameterTypes()[0];
1120
360
        ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
1121
360
        solAssert(arrayType, "");
1122
1123
        // stack: ArrayReference
1124
360
        arguments[0]->accept(*this);
1125
360
        Type const* argType = arguments[0]->annotation().type;
1126
        // stack: ArrayReference argValue
1127
360
        utils().moveToStackTop(argType->sizeOnStack(), 1);
1128
        // stack: argValue ArrayReference
1129
360
        m_context << Instruction::DUP1;
1130
360
        ArrayUtils(m_context).incrementDynamicArraySize(*arrayType);
1131
        // stack: argValue ArrayReference newLength
1132
360
        m_context << u256(1) << Instruction::SWAP1 << Instruction::SUB;
1133
        // stack: argValue ArrayReference (newLength-1)
1134
360
        ArrayUtils(m_context).accessIndex(*arrayType, false);
1135
        // stack: argValue storageSlot slotOffset
1136
360
        utils().moveToStackTop(2, argType->sizeOnStack());
1137
        // stack: storageSlot slotOffset argValue
1138
360
        Type const* type =
1139
360
          arrayType->baseType()->dataStoredIn(DataLocation::Storage) ?
1140
94
          arguments[0]->annotation().type->mobileType() :
1141
360
          arrayType->baseType();
1142
360
        solAssert(type, "");
1143
360
        utils().convertType(*argType, *type);
1144
360
        utils().moveToStackTop(1 + type->sizeOnStack());
1145
360
        utils().moveToStackTop(1 + type->sizeOnStack());
1146
        // stack: argValue storageSlot slotOffset
1147
360
        if (!arrayType->isByteArrayOrString())
1148
295
          StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true);
1149
65
        else
1150
65
          StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true);
1151
360
      }
1152
3.04k
      break;
1153
3.04k
    }
1154
3.04k
    case FunctionType::Kind::ArrayPop:
1155
166
    {
1156
166
      _functionCall.expression().accept(*this);
1157
166
      solAssert(function.hasBoundFirstArgument(), "");
1158
166
      solAssert(function.parameterTypes().empty(), "");
1159
166
      ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
1160
166
      solAssert(arrayType && arrayType->dataStoredIn(DataLocation::Storage), "");
1161
166
      ArrayUtils(m_context).popStorageArrayElement(*arrayType);
1162
166
      break;
1163
166
    }
1164
9
    case FunctionType::Kind::StringConcat:
1165
44
    case FunctionType::Kind::BytesConcat:
1166
44
    {
1167
44
      _functionCall.expression().accept(*this);
1168
44
      std::vector<Type const*> argumentTypes;
1169
44
      std::vector<Type const*> targetTypes;
1170
44
      for (auto const& argument: arguments)
1171
106
      {
1172
106
        argument->accept(*this);
1173
106
        solAssert(argument->annotation().type, "");
1174
106
        argumentTypes.emplace_back(argument->annotation().type);
1175
106
        if (argument->annotation().type->category() == Type::Category::FixedBytes)
1176
6
          targetTypes.emplace_back(argument->annotation().type);
1177
100
        else if (
1178
100
          auto const* literalType = dynamic_cast<StringLiteralType const*>(argument->annotation().type);
1179
100
          literalType && !literalType->value().empty() && literalType->value().size() <= 32
1180
100
        )
1181
16
          targetTypes.emplace_back(TypeProvider::fixedBytes(static_cast<unsigned>(literalType->value().size())));
1182
84
        else
1183
84
        {
1184
84
          solAssert(!dynamic_cast<RationalNumberType const*>(argument->annotation().type), "");
1185
84
          if (function.kind() == FunctionType::Kind::StringConcat)
1186
18
          {
1187
18
            solAssert(argument->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::stringMemory()), "");
1188
18
            targetTypes.emplace_back(TypeProvider::stringMemory());
1189
18
          }
1190
66
          else if (function.kind() == FunctionType::Kind::BytesConcat)
1191
66
          {
1192
66
            solAssert(argument->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()), "");
1193
66
            targetTypes.emplace_back(TypeProvider::bytesMemory());
1194
66
          }
1195
84
        }
1196
106
      }
1197
44
      utils().fetchFreeMemoryPointer();
1198
      // stack: <arg1> <arg2> ... <argn> <free mem>
1199
44
      m_context << u256(32) << Instruction::ADD;
1200
44
      utils().packedEncode(argumentTypes, targetTypes);
1201
44
      utils().fetchFreeMemoryPointer();
1202
44
      m_context.appendInlineAssembly(R"({
1203
44
        mstore(mem_ptr, sub(sub(mem_end, mem_ptr), 0x20))
1204
44
      })", {"mem_end", "mem_ptr"});
1205
44
      m_context << Instruction::SWAP1;
1206
44
      utils().storeFreeMemoryPointer();
1207
1208
44
      break;
1209
44
    }
1210
2.08k
    case FunctionType::Kind::ObjectCreation:
1211
2.08k
    {
1212
2.08k
      ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_functionCall.annotation().type);
1213
2.08k
      _functionCall.expression().accept(*this);
1214
2.08k
      solAssert(arguments.size() == 1, "");
1215
1216
      // Fetch requested length.
1217
2.08k
      acceptAndConvert(*arguments[0], *TypeProvider::uint256());
1218
1219
      // Make sure we can allocate memory without overflow
1220
2.08k
      m_context << u256(0xffffffffffffffff);
1221
2.08k
      m_context << Instruction::DUP2;
1222
2.08k
      m_context << Instruction::GT;
1223
2.08k
      m_context.appendConditionalPanic(PanicCode::ResourceError);
1224
1225
      // Stack: requested_length
1226
2.08k
      utils().fetchFreeMemoryPointer();
1227
1228
      // Stack: requested_length memptr
1229
2.08k
      m_context << Instruction::SWAP1;
1230
      // Stack: memptr requested_length
1231
      // store length
1232
2.08k
      m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE;
1233
      // Stack: memptr requested_length
1234
      // update free memory pointer
1235
2.08k
      m_context << Instruction::DUP1;
1236
      // Stack: memptr requested_length requested_length
1237
2.08k
      if (arrayType.isByteArrayOrString())
1238
        // Round up to multiple of 32
1239
561
        m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
1240
1.52k
      else
1241
1.52k
        m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL;
1242
      // stacK: memptr requested_length data_size
1243
2.08k
      m_context << u256(32) << Instruction::ADD;
1244
2.08k
      m_context << Instruction::DUP3 << Instruction::ADD;
1245
2.08k
      utils().storeFreeMemoryPointer();
1246
      // Stack: memptr requested_length
1247
1248
      // Check if length is zero
1249
2.08k
      m_context << Instruction::DUP1 << Instruction::ISZERO;
1250
2.08k
      auto skipInit = m_context.appendConditionalJump();
1251
      // Always initialize because the free memory pointer might point at
1252
      // a dirty memory area.
1253
2.08k
      m_context << Instruction::DUP2 << u256(32) << Instruction::ADD;
1254
2.08k
      utils().zeroInitialiseMemoryArray(arrayType);
1255
2.08k
      m_context << skipInit;
1256
2.08k
      m_context << Instruction::POP;
1257
2.08k
      break;
1258
2.08k
    }
1259
2.05k
    case FunctionType::Kind::Assert:
1260
2.45k
    case FunctionType::Kind::Require:
1261
2.45k
    {
1262
2.45k
      acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), false);
1263
      // stack: <condition>
1264
2.45k
      bool haveReasonString = arguments.size() > 1 && m_context.revertStrings() != RevertStrings::Strip;
1265
2.45k
      if (arguments.size() > 1)
1266
33
      {
1267
        // Users probably expect the second argument to be evaluated
1268
        // even if the condition is false, as would be the case for an actual
1269
        // function call.
1270
33
        solAssert(arguments.size() == 2, "");
1271
33
        solAssert(function.kind() == FunctionType::Kind::Require, "");
1272
33
        auto const* magicType = dynamic_cast<MagicType const*>(arguments[1]->annotation().type);
1273
33
        if (magicType && magicType->kind() == MagicType::Kind::Error)
1274
2
        {
1275
          // Make sure that error constructor arguments are evaluated regardless of the require condition
1276
2
          auto const& errorConstructorCall = dynamic_cast<FunctionCall const&>(*arguments[1]);
1277
2
          errorConstructorCall.expression().accept(*this);
1278
2
          std::vector<Type const*> errorConstructorArgumentTypes{};
1279
2
          for (ASTPointer<Expression const> const& errorConstructorArgument: errorConstructorCall.sortedArguments())
1280
4
          {
1281
4
            errorConstructorArgument->accept(*this);
1282
4
            errorConstructorArgumentTypes.push_back(errorConstructorArgument->annotation().type);
1283
4
          }
1284
2
          unsigned const sizeOfConditionArgument = arguments.at(0)->annotation().type->sizeOnStack();
1285
2
          unsigned const sizeOfErrorArguments = CompilerUtils::sizeOnStack(errorConstructorArgumentTypes);
1286
          // stack: <condition> <arg0> <arg1> ... <argN>
1287
2
          try
1288
2
          {
1289
            // Move condition to the top of the stack
1290
2
            utils().moveToStackTop(sizeOfErrorArguments, sizeOfConditionArgument);
1291
2
          }
1292
2
          catch (StackTooDeepError const& _exception)
1293
2
          {
1294
0
            _exception << errinfo_sourceLocation(errorConstructorCall.location());
1295
0
            throw _exception;
1296
0
          }
1297
          // stack: <arg0> <arg1> ... <argN> <condition>
1298
2
          m_context << Instruction::ISZERO << Instruction::ISZERO;
1299
2
          AssemblyItem successBranchTag = m_context.appendConditionalJump();
1300
1301
2
          auto const* errorDefinition = dynamic_cast<ErrorDefinition const*>(ASTNode::referencedDeclaration(errorConstructorCall.expression()));
1302
2
          solAssert(errorDefinition && errorDefinition->functionType(true));
1303
2
          utils().revertWithError(
1304
2
            errorDefinition->functionType(true)->externalSignature(),
1305
2
            errorDefinition->functionType(true)->parameterTypes(),
1306
2
            errorConstructorArgumentTypes
1307
2
          );
1308
          // Here, the argument is consumed, but in the other branch, it is still there.
1309
2
          m_context.adjustStackOffset(static_cast<int>(sizeOfErrorArguments));
1310
2
          m_context << successBranchTag;
1311
          // In case of the success branch i.e. require(true, ...), pop error constructor arguments
1312
2
          utils().popStackSlots(sizeOfErrorArguments);
1313
2
          break;
1314
2
        }
1315
1316
31
        if (m_context.revertStrings() == RevertStrings::Strip)
1317
0
        {
1318
0
          if (!*arguments.at(1)->annotation().isPure)
1319
0
          {
1320
0
            arguments.at(1)->accept(*this);
1321
0
            utils().popStackElement(*arguments.at(1)->annotation().type);
1322
0
          }
1323
0
        }
1324
31
        else
1325
31
        {
1326
31
          arguments.at(1)->accept(*this);
1327
31
          utils().moveIntoStack(1, arguments.at(1)->annotation().type->sizeOnStack());
1328
31
        }
1329
31
      }
1330
      // Stack: <error string (unconverted)> <condition>
1331
      // jump if condition was met
1332
2.44k
      m_context << Instruction::ISZERO << Instruction::ISZERO;
1333
2.44k
      auto success = m_context.appendConditionalJump();
1334
2.44k
      if (function.kind() == FunctionType::Kind::Assert)
1335
        // condition was not met, flag an error
1336
2.05k
        m_context.appendPanic(util::PanicCode::Assert);
1337
397
      else if (haveReasonString)
1338
31
      {
1339
31
        utils().revertWithStringData(*arguments.at(1)->annotation().type);
1340
        // Here, the argument is consumed, but in the other branch, it is still there.
1341
31
        m_context.adjustStackOffset(static_cast<int>(arguments.at(1)->annotation().type->sizeOnStack()));
1342
31
      }
1343
366
      else
1344
366
        m_context.appendRevert();
1345
      // the success branch
1346
2.44k
      m_context << success;
1347
2.44k
      if (haveReasonString)
1348
31
        utils().popStackElement(*arguments.at(1)->annotation().type);
1349
2.44k
      break;
1350
2.45k
    }
1351
384
    case FunctionType::Kind::ABIEncode:
1352
483
    case FunctionType::Kind::ABIEncodePacked:
1353
505
    case FunctionType::Kind::ABIEncodeWithSelector:
1354
531
    case FunctionType::Kind::ABIEncodeCall:
1355
553
    case FunctionType::Kind::ABIEncodeWithSignature:
1356
553
    {
1357
553
      bool const isPacked = function.kind() == FunctionType::Kind::ABIEncodePacked;
1358
553
      bool const hasSelectorOrSignature =
1359
553
        function.kind() == FunctionType::Kind::ABIEncodeWithSelector ||
1360
553
        function.kind() == FunctionType::Kind::ABIEncodeCall ||
1361
553
        function.kind() == FunctionType::Kind::ABIEncodeWithSignature;
1362
1363
553
      TypePointers argumentTypes;
1364
553
      TypePointers targetTypes;
1365
1366
553
      ASTNode::listAccept(arguments, *this);
1367
1368
553
      if (function.kind() == FunctionType::Kind::ABIEncodeCall)
1369
26
      {
1370
26
        solAssert(arguments.size() == 2);
1371
1372
        // Account for tuples with one component which become that component
1373
26
        if (auto const tupleType = dynamic_cast<TupleType const*>(arguments[1]->annotation().type))
1374
5
          argumentTypes = tupleType->components();
1375
21
        else
1376
21
          argumentTypes.emplace_back(arguments[1]->annotation().type);
1377
1378
26
        auto functionPtr = dynamic_cast<FunctionTypePointer>(arguments[0]->annotation().type);
1379
26
        solAssert(functionPtr);
1380
26
        functionPtr = functionPtr->asExternallyCallableFunction(false);
1381
26
        solAssert(functionPtr);
1382
26
        targetTypes = functionPtr->parameterTypes();
1383
26
      }
1384
527
      else
1385
1.35k
        for (unsigned i = 0; i < arguments.size(); ++i)
1386
823
        {
1387
          // Do not keep the selector as part of the ABI encoded args
1388
823
          if (!hasSelectorOrSignature || i > 0)
1389
779
            argumentTypes.push_back(arguments[i]->annotation().type);
1390
823
        }
1391
1392
553
      utils().fetchFreeMemoryPointer();
1393
      // stack now: [<selector/functionPointer/signature>] <arg1> .. <argN> <free_mem>
1394
1395
      // adjust by 32(+4) bytes to accommodate the length(+selector)
1396
553
      m_context << u256(32 + (hasSelectorOrSignature ? 4 : 0)) << Instruction::ADD;
1397
      // stack now: [<selector/functionPointer/signature>] <arg1> .. <argN> <data_encoding_area_start>
1398
1399
553
      if (isPacked)
1400
99
      {
1401
99
        solAssert(!function.padArguments(), "");
1402
99
        utils().packedEncode(argumentTypes, targetTypes);
1403
99
      }
1404
454
      else
1405
454
      {
1406
454
        solAssert(function.padArguments(), "");
1407
454
        utils().abiEncode(argumentTypes, targetTypes);
1408
454
      }
1409
553
      utils().fetchFreeMemoryPointer();
1410
      // stack: [<selector/functionPointer/signature>] <data_encoding_area_end> <bytes_memory_ptr>
1411
1412
      // size is end minus start minus length slot
1413
553
      m_context.appendInlineAssembly(R"({
1414
553
        mstore(mem_ptr, sub(sub(mem_end, mem_ptr), 0x20))
1415
553
      })", {"mem_end", "mem_ptr"});
1416
553
      m_context << Instruction::SWAP1;
1417
553
      utils().storeFreeMemoryPointer();
1418
      // stack: [<selector/functionPointer/signature>] <memory ptr>
1419
1420
553
      if (hasSelectorOrSignature)
1421
70
      {
1422
        // stack: <selector/functionPointer/signature> <memory pointer>
1423
70
        solAssert(arguments.size() >= 1, "");
1424
70
        Type const* selectorType = arguments[0]->annotation().type;
1425
70
        utils().moveIntoStack(selectorType->sizeOnStack());
1426
70
        Type const* dataOnStack = selectorType;
1427
1428
        // stack: <memory pointer> <selector/functionPointer/signature>
1429
70
        if (function.kind() == FunctionType::Kind::ABIEncodeWithSignature)
1430
22
        {
1431
          // hash the signature
1432
22
          if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType))
1433
20
          {
1434
20
            m_context << util::selectorFromSignatureU256(stringType->value());
1435
20
            dataOnStack = TypeProvider::fixedBytes(4);
1436
20
          }
1437
2
          else
1438
2
          {
1439
2
            utils().fetchFreeMemoryPointer();
1440
            // stack: <memory pointer> <signature> <free mem ptr>
1441
2
            utils().packedEncode(TypePointers{selectorType}, TypePointers());
1442
2
            utils().toSizeAfterFreeMemoryPointer();
1443
2
            m_context << Instruction::KECCAK256;
1444
            // stack: <memory pointer> <hash>
1445
1446
2
            dataOnStack = TypeProvider::fixedBytes(32);
1447
2
          }
1448
22
        }
1449
48
        else if (function.kind() == FunctionType::Kind::ABIEncodeCall)
1450
26
        {
1451
26
          auto const& funType = dynamic_cast<FunctionType const&>(*selectorType);
1452
26
          if (funType.kind() == FunctionType::Kind::Declaration)
1453
2
          {
1454
2
            solAssert(funType.hasDeclaration());
1455
2
            solAssert(selectorType->sizeOnStack() == 0);
1456
2
            m_context << funType.externalIdentifier();
1457
2
          }
1458
24
          else
1459
24
          {
1460
24
            solAssert(selectorType->sizeOnStack() == 2);
1461
            // stack: <memory pointer> <functionPointer>
1462
            // Extract selector from the stack
1463
24
            m_context << Instruction::SWAP1 << Instruction::POP;
1464
24
          }
1465
          // Conversion will be done below
1466
26
          dataOnStack = TypeProvider::uint(32);
1467
26
        }
1468
22
        else
1469
48
          solAssert(function.kind() == FunctionType::Kind::ABIEncodeWithSelector, "");
1470
1471
70
        utils().convertType(*dataOnStack, FixedBytesType(4), true);
1472
1473
        // stack: <memory pointer> <selector>
1474
1475
        // load current memory, mask and combine the selector
1476
70
        std::string mask = formatNumber((u256(-1) >> 32));
1477
70
        m_context.appendInlineAssembly(R"({
1478
70
          let data_start := add(mem_ptr, 0x20)
1479
70
          let data := mload(data_start)
1480
70
          let mask := )" + mask + R"(
1481
70
          mstore(data_start, or(and(data, mask), selector))
1482
70
        })", {"mem_ptr", "selector"});
1483
70
        m_context << Instruction::POP;
1484
70
      }
1485
1486
      // stack now: <memory pointer>
1487
553
      break;
1488
553
    }
1489
553
    case FunctionType::Kind::ABIDecode:
1490
366
    {
1491
366
      arguments.front()->accept(*this);
1492
366
      Type const* firstArgType = arguments.front()->annotation().type;
1493
366
      TypePointers targetTypes;
1494
366
      if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type))
1495
18
        targetTypes = targetTupleType->components();
1496
348
      else
1497
348
        targetTypes = TypePointers{_functionCall.annotation().type};
1498
366
      if (
1499
366
        auto referenceType = dynamic_cast<ReferenceType const*>(firstArgType);
1500
366
        referenceType && referenceType->dataStoredIn(DataLocation::CallData)
1501
366
      )
1502
28
      {
1503
28
        solAssert(referenceType->isImplicitlyConvertibleTo(*TypeProvider::bytesCalldata()), "");
1504
28
        utils().convertType(*referenceType, *TypeProvider::bytesCalldata());
1505
28
        utils().abiDecode(targetTypes, false);
1506
28
      }
1507
338
      else
1508
338
      {
1509
338
        utils().convertType(*firstArgType, *TypeProvider::bytesMemory());
1510
338
        m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
1511
338
        m_context << Instruction::SWAP1 << Instruction::MLOAD;
1512
        // stack now: <mem_pos> <length>
1513
1514
338
        utils().abiDecode(targetTypes, true);
1515
338
      }
1516
366
      break;
1517
366
    }
1518
366
    case FunctionType::Kind::GasLeft:
1519
32
      m_context << Instruction::GAS;
1520
32
      break;
1521
134
    case FunctionType::Kind::MetaType:
1522
      // No code to generate.
1523
134
      break;
1524
24.2k
    }
1525
24.2k
  }
1526
24.3k
  return false;
1527
24.4k
}
1528
1529
bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
1530
113
{
1531
113
  _functionCallOptions.expression().accept(*this);
1532
1533
  // Desired Stack: [salt], [gas], [value]
1534
113
  enum Option { Salt, Gas, Value };
1535
1536
113
  std::vector<Option> presentOptions;
1537
113
  FunctionType const& funType = dynamic_cast<FunctionType const&>(
1538
113
    *_functionCallOptions.expression().annotation().type
1539
113
  );
1540
113
  if (funType.saltSet()) presentOptions.emplace_back(Salt);
1541
113
  if (funType.gasSet()) presentOptions.emplace_back(Gas);
1542
113
  if (funType.valueSet()) presentOptions.emplace_back(Value);
1543
1544
230
  for (size_t i = 0; i < _functionCallOptions.options().size(); ++i)
1545
117
  {
1546
117
    std::string const& name = *_functionCallOptions.names()[i];
1547
117
    Type const* requiredType = TypeProvider::uint256();
1548
117
    Option newOption;
1549
117
    if (name == "salt")
1550
12
    {
1551
12
      newOption = Salt;
1552
12
      requiredType = TypeProvider::fixedBytes(32);
1553
12
    }
1554
105
    else if (name == "gas")
1555
34
      newOption = Gas;
1556
71
    else if (name == "value")
1557
71
      newOption = Value;
1558
0
    else
1559
71
      solAssert(false, "Unexpected option name!");
1560
117
    acceptAndConvert(*_functionCallOptions.options()[i], *requiredType);
1561
1562
117
    solAssert(!util::contains(presentOptions, newOption), "");
1563
117
    ptrdiff_t insertPos = presentOptions.end() - lower_bound(presentOptions.begin(), presentOptions.end(), newOption);
1564
1565
117
    utils().moveIntoStack(static_cast<unsigned>(insertPos), 1);
1566
117
    presentOptions.insert(presentOptions.end() - insertPos, newOption);
1567
117
  }
1568
1569
113
  return false;
1570
113
}
1571
1572
bool ExpressionCompiler::visit(NewExpression const&)
1573
2.28k
{
1574
  // code is created for the function call (CREATION) only
1575
2.28k
  return false;
1576
2.28k
}
1577
1578
bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
1579
196k
{
1580
196k
  CompilerContext::LocationSetter locationSetter(m_context, _memberAccess);
1581
  // Check whether the member is an attached function.
1582
196k
  ASTString const& member = _memberAccess.memberName();
1583
196k
  if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
1584
7.92k
    if (funType->hasBoundFirstArgument())
1585
3.40k
    {
1586
3.40k
      acceptAndConvert(_memberAccess.expression(), *funType->selfType(), true);
1587
3.40k
      if (funType->kind() == FunctionType::Kind::Internal)
1588
113
      {
1589
113
        FunctionDefinition const& funDef = dynamic_cast<decltype(funDef)>(funType->declaration());
1590
113
        solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
1591
113
        utils().pushCombinedFunctionEntryLabel(
1592
113
          funDef,
1593
          // If we call directly, do not include the second label.
1594
113
          !_memberAccess.annotation().calledDirectly
1595
113
        );
1596
113
        utils().moveIntoStack(funType->selfType()->sizeOnStack(), 1);
1597
113
      }
1598
3.29k
      else if (
1599
3.29k
        funType->kind() == FunctionType::Kind::ArrayPop ||
1600
3.29k
        funType->kind() == FunctionType::Kind::ArrayPush
1601
3.29k
      )
1602
3.24k
      {
1603
3.24k
      }
1604
45
      else
1605
45
      {
1606
45
        solAssert(funType->kind() == FunctionType::Kind::DelegateCall, "");
1607
45
        auto contract = dynamic_cast<ContractDefinition const*>(funType->declaration().scope());
1608
45
        solAssert(contract && contract->isLibrary(), "");
1609
45
        m_context.appendLibraryAddress(contract->fullyQualifiedName());
1610
45
        m_context << funType->externalIdentifier();
1611
45
        utils().moveIntoStack(funType->selfType()->sizeOnStack(), 2);
1612
45
      }
1613
3.40k
      return false;
1614
3.40k
    }
1615
1616
  // Special processing for TypeType because we do not want to visit the library itself
1617
  // for internal functions, or enum/struct definitions.
1618
193k
  if (TypeType const* type = dynamic_cast<TypeType const*>(_memberAccess.expression().annotation().type))
1619
633
  {
1620
633
    if (auto contractType = dynamic_cast<ContractType const*>(type->actualType()))
1621
493
    {
1622
493
      solAssert(_memberAccess.annotation().type, "_memberAccess has no type");
1623
493
      if (contractType->isSuper())
1624
65
      {
1625
65
        _memberAccess.expression().accept(*this);
1626
65
        solAssert(_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved.");
1627
65
        solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Super, "");
1628
65
        utils().pushCombinedFunctionEntryLabel(
1629
65
          m_context.superFunction(
1630
65
            dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration),
1631
65
            contractType->contractDefinition()
1632
65
          ),
1633
          // If we call directly, do not include the second label.
1634
65
          !_memberAccess.annotation().calledDirectly
1635
65
        );
1636
65
      }
1637
428
      else
1638
428
      {
1639
428
        if (auto variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
1640
59
          appendVariable(*variable, static_cast<Expression const&>(_memberAccess));
1641
369
        else if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
1642
348
        {
1643
348
          switch (funType->kind())
1644
348
          {
1645
31
          case FunctionType::Kind::Declaration:
1646
31
            break;
1647
115
          case FunctionType::Kind::Internal:
1648
            // We do not visit the expression here on purpose, because in the case of an
1649
            // internal library function call, this would push the library address forcing
1650
            // us to link against it although we actually do not need it.
1651
115
            if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
1652
115
            {
1653
115
              solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
1654
115
              utils().pushCombinedFunctionEntryLabel(
1655
115
                *function,
1656
                // If we call directly, do not include the second label.
1657
115
                !_memberAccess.annotation().calledDirectly
1658
115
              );
1659
115
            }
1660
0
            else
1661
115
              solAssert(false, "Function not found in member access");
1662
115
            break;
1663
115
          case FunctionType::Kind::Event:
1664
68
            if (!dynamic_cast<EventDefinition const*>(_memberAccess.annotation().referencedDeclaration))
1665
68
              solAssert(false, "event not found");
1666
            // no-op, because the parent node will do the job
1667
68
            break;
1668
68
          case FunctionType::Kind::Error:
1669
9
            if (!dynamic_cast<ErrorDefinition const*>(_memberAccess.annotation().referencedDeclaration))
1670
9
              solAssert(false, "error not found");
1671
            // no-op, because the parent node will do the job
1672
9
            break;
1673
125
          case FunctionType::Kind::DelegateCall:
1674
125
            _memberAccess.expression().accept(*this);
1675
125
            m_context << funType->externalIdentifier();
1676
125
          break;
1677
0
          case FunctionType::Kind::External:
1678
0
          case FunctionType::Kind::Creation:
1679
0
          case FunctionType::Kind::Send:
1680
0
          case FunctionType::Kind::BareCall:
1681
0
          case FunctionType::Kind::BareCallCode:
1682
0
          case FunctionType::Kind::BareDelegateCall:
1683
0
          case FunctionType::Kind::BareStaticCall:
1684
0
          case FunctionType::Kind::Transfer:
1685
0
          case FunctionType::Kind::ECRecover:
1686
0
          case FunctionType::Kind::SHA256:
1687
0
          case FunctionType::Kind::RIPEMD160:
1688
0
          default:
1689
0
            solAssert(false, "unsupported member function");
1690
348
          }
1691
348
        }
1692
21
        else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type))
1693
21
        {
1694
          // no-op
1695
21
        }
1696
0
        else
1697
0
          _memberAccess.expression().accept(*this);
1698
428
      }
1699
493
    }
1700
140
    else if (auto enumType = dynamic_cast<EnumType const*>(type->actualType()))
1701
78
    {
1702
78
      _memberAccess.expression().accept(*this);
1703
78
      m_context << enumType->memberValue(_memberAccess.memberName());
1704
78
    }
1705
62
    else
1706
62
      _memberAccess.expression().accept(*this);
1707
633
    return false;
1708
633
  }
1709
  // Another special case for `this.f.selector` and for ``C.f.selector`` which do not need the address.
1710
  // There are other uses of `.selector` which do need the address, but we want these
1711
  // specific uses to be pure expressions.
1712
192k
  if (
1713
192k
    auto const* functionType = dynamic_cast<FunctionType const*>(_memberAccess.expression().annotation().type);
1714
192k
    functionType && member == "selector"
1715
192k
  )
1716
639
  {
1717
639
    if (functionType->hasDeclaration())
1718
625
    {
1719
      // Still visit the expression in case it has side effects.
1720
625
      _memberAccess.expression().accept(*this);
1721
625
      utils().popStackElement(*functionType);
1722
1723
625
      if (functionType->kind() == FunctionType::Kind::Event)
1724
11
        m_context << u256(h256::Arith(util::keccak256(functionType->externalSignature())));
1725
614
      else
1726
614
      {
1727
614
        m_context << functionType->externalIdentifier();
1728
        /// need to store it as bytes4
1729
614
        utils().leftShiftNumberOnStack(224);
1730
614
      }
1731
625
      return false;
1732
625
    }
1733
14
    else if (auto const* expr = dynamic_cast<MemberAccess const*>(&_memberAccess.expression()))
1734
0
      if (auto const* exprInt = dynamic_cast<Identifier const*>(&expr->expression()))
1735
0
        if (exprInt->name() == "this")
1736
0
          if (Declaration const* declaration = expr->annotation().referencedDeclaration)
1737
0
          {
1738
0
            u256 identifier;
1739
0
            if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration))
1740
0
              identifier = FunctionType(*variable).externalIdentifier();
1741
0
            else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration))
1742
0
              identifier = FunctionType(*function).externalIdentifier();
1743
0
            else
1744
0
              solAssert(false, "Contract member is neither variable nor function.");
1745
0
            m_context << identifier;
1746
            /// need to store it as bytes4
1747
0
            utils().leftShiftNumberOnStack(224);
1748
0
            return false;
1749
0
          }
1750
639
  }
1751
  // Another special case for `address(this).balance`. Post-Istanbul, we can use the selfbalance
1752
  // opcode.
1753
191k
  if (
1754
191k
    m_context.evmVersion().hasSelfBalance() &&
1755
191k
    member == "balance" &&
1756
191k
    _memberAccess.expression().annotation().type->category() == Type::Category::Address
1757
191k
  )
1758
63
    if (FunctionCall const* funCall = dynamic_cast<FunctionCall const*>(&_memberAccess.expression()))
1759
39
      if (auto const* addr = dynamic_cast<ElementaryTypeNameExpression const*>(&funCall->expression()))
1760
37
        if (
1761
37
          addr->type().typeName().token() == Token::Address &&
1762
37
          funCall->arguments().size() == 1
1763
37
        )
1764
37
          if (auto arg = dynamic_cast<Identifier const*>( funCall->arguments().front().get()))
1765
31
            if (
1766
31
              arg->name() == "this" &&
1767
31
              dynamic_cast<MagicVariableDeclaration const*>(arg->annotation().referencedDeclaration)
1768
31
            )
1769
29
            {
1770
29
              m_context << Instruction::SELFBALANCE;
1771
29
              return false;
1772
29
            }
1773
1774
  // Another special case for `address.code.length`, which should simply call extcodesize
1775
191k
  if (
1776
191k
    auto innerExpression = dynamic_cast<MemberAccess const*>(&_memberAccess.expression());
1777
191k
    member == "length" &&
1778
191k
    innerExpression &&
1779
191k
    innerExpression->memberName() == "code" &&
1780
191k
    innerExpression->expression().annotation().type->category() == Type::Category::Address
1781
191k
  )
1782
6
  {
1783
6
    solAssert(innerExpression->annotation().type->category() == Type::Category::Array, "");
1784
1785
6
    innerExpression->expression().accept(*this);
1786
1787
6
    utils().convertType(
1788
6
      *innerExpression->expression().annotation().type,
1789
6
      *TypeProvider::address(),
1790
6
      true
1791
6
    );
1792
6
    m_context << Instruction::EXTCODESIZE;
1793
1794
6
    return false;
1795
6
  }
1796
1797
191k
  _memberAccess.expression().accept(*this);
1798
191k
  switch (_memberAccess.expression().annotation().type->category())
1799
191k
  {
1800
3.09k
  case Type::Category::Contract:
1801
3.09k
  {
1802
3.09k
    ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type);
1803
    // ordinary contract type
1804
3.09k
    if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration)
1805
3.09k
    {
1806
3.09k
      u256 identifier;
1807
3.09k
      if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration))
1808
181
        identifier = FunctionType(*variable).externalIdentifier();
1809
2.91k
      else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration))
1810
2.91k
        identifier = FunctionType(*function).externalIdentifier();
1811
0
      else
1812
2.91k
        solAssert(false, "Contract member is neither variable nor function.");
1813
3.09k
      utils().convertType(type, type.isPayable() ? *TypeProvider::payableAddress() : *TypeProvider::address(), true);
1814
3.09k
      m_context << identifier;
1815
3.09k
    }
1816
0
    else
1817
3.09k
      solAssert(false, "Invalid member access in contract");
1818
3.09k
    break;
1819
3.09k
  }
1820
3.09k
  case Type::Category::Integer:
1821
0
  {
1822
0
    solAssert(false, "Invalid member access to integer");
1823
0
    break;
1824
0
  }
1825
925
  case Type::Category::Address:
1826
925
  {
1827
925
    if (member == "balance")
1828
67
    {
1829
67
      utils().convertType(
1830
67
        *_memberAccess.expression().annotation().type,
1831
67
        *TypeProvider::address(),
1832
67
        true
1833
67
      );
1834
67
      m_context << Instruction::BALANCE;
1835
67
    }
1836
858
    else if (member == "code")
1837
9
    {
1838
      // Stack: <address>
1839
9
      utils().convertType(
1840
9
        *_memberAccess.expression().annotation().type,
1841
9
        *TypeProvider::address(),
1842
9
        true
1843
9
      );
1844
1845
9
      m_context << Instruction::DUP1 << Instruction::EXTCODESIZE;
1846
      // Stack post: <address> <size>
1847
1848
9
      m_context << Instruction::DUP1;
1849
      // Account for the size field of `bytes memory`
1850
9
      m_context << u256(32) << Instruction::ADD;
1851
9
      utils().allocateMemory();
1852
      // Stack post: <address> <size> <mem_offset>
1853
1854
      // Store size at mem_offset
1855
9
      m_context << Instruction::DUP2 << Instruction::DUP2 << Instruction::MSTORE;
1856
1857
9
      m_context << u256(0) << Instruction::SWAP1 << Instruction::DUP1;
1858
      // Stack post: <address> <size> 0 <mem_offset> <mem_offset>
1859
1860
9
      m_context << u256(32) << Instruction::ADD << Instruction::SWAP1;
1861
      // Stack post: <address> <size> 0 <mem_offset_adjusted> <mem_offset>
1862
1863
9
      m_context << Instruction::SWAP4;
1864
      // Stack post: <mem_offset> <size> 0 <mem_offset_adjusted> <address>
1865
1866
9
      m_context << Instruction::EXTCODECOPY;
1867
      // Stack post: <mem_offset>
1868
9
    }
1869
849
    else if (member == "codehash")
1870
12
    {
1871
12
      utils().convertType(
1872
12
        *_memberAccess.expression().annotation().type,
1873
12
        *TypeProvider::address(),
1874
12
        true
1875
12
      );
1876
12
      m_context << Instruction::EXTCODEHASH;
1877
12
    }
1878
837
    else if ((std::set<std::string>{"send", "transfer"}).count(member))
1879
65
    {
1880
65
      solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, "");
1881
65
      utils().convertType(
1882
65
        *_memberAccess.expression().annotation().type,
1883
65
        AddressType(StateMutability::Payable),
1884
65
        true
1885
65
      );
1886
65
    }
1887
772
    else if ((std::set<std::string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
1888
772
      utils().convertType(
1889
772
        *_memberAccess.expression().annotation().type,
1890
772
        *TypeProvider::address(),
1891
772
        true
1892
772
      );
1893
0
    else
1894
772
      solAssert(false, "Invalid member access to address");
1895
925
    break;
1896
925
  }
1897
925
  case Type::Category::Function:
1898
52
    if (member == "selector")
1899
14
    {
1900
14
      auto const& functionType = dynamic_cast<FunctionType const&>(*_memberAccess.expression().annotation().type);
1901
      // all events should have already been caught by this stage
1902
14
      solAssert(!(functionType.kind() == FunctionType::Kind::Event));
1903
1904
14
      if (functionType.kind() == FunctionType::Kind::External)
1905
14
        CompilerUtils(m_context).popStackSlots(functionType.sizeOnStack() - 2);
1906
14
      m_context << Instruction::SWAP1 << Instruction::POP;
1907
1908
      /// need to store it as bytes4
1909
14
      utils().leftShiftNumberOnStack(224);
1910
14
    }
1911
38
    else if (member == "address")
1912
38
    {
1913
38
      auto const& functionType = dynamic_cast<FunctionType const&>(*_memberAccess.expression().annotation().type);
1914
38
      solAssert(functionType.kind() == FunctionType::Kind::External, "");
1915
38
      CompilerUtils(m_context).popStackSlots(functionType.sizeOnStack() - 1);
1916
38
    }
1917
0
    else
1918
38
      solAssert(
1919
52
        !!_memberAccess.expression().annotation().type->memberType(member),
1920
52
        "Invalid member access to function."
1921
52
      );
1922
52
    break;
1923
582
  case Type::Category::Magic:
1924
    // we can ignore the kind of magic and only look at the name of the member
1925
582
    if (member == "coinbase")
1926
8
      m_context << Instruction::COINBASE;
1927
574
    else if (member == "timestamp")
1928
16
      m_context << Instruction::TIMESTAMP;
1929
558
    else if (member == "difficulty" || member == "prevrandao")
1930
18
      m_context << Instruction::PREVRANDAO;
1931
540
    else if (member == "number")
1932
9
      m_context << Instruction::NUMBER;
1933
531
    else if (member == "gaslimit")
1934
8
      m_context << Instruction::GASLIMIT;
1935
523
    else if (member == "sender")
1936
120
      m_context << Instruction::CALLER;
1937
403
    else if (member == "value")
1938
73
      m_context << Instruction::CALLVALUE;
1939
330
    else if (member == "origin")
1940
7
      m_context << Instruction::ORIGIN;
1941
323
    else if (member == "gasprice")
1942
7
      m_context << Instruction::GASPRICE;
1943
316
    else if (member == "chainid")
1944
8
      m_context << Instruction::CHAINID;
1945
308
    else if (member == "basefee")
1946
16
      m_context << Instruction::BASEFEE;
1947
292
    else if (member == "blobbasefee")
1948
2
      m_context << Instruction::BLOBBASEFEE;
1949
290
    else if (member == "data")
1950
113
      m_context << u256(0) << Instruction::CALLDATASIZE;
1951
177
    else if (member == "sig")
1952
16
      m_context << u256(0) << Instruction::CALLDATALOAD
1953
16
        << (u256(0xffffffff) << (256 - 32)) << Instruction::AND;
1954
161
    else if (member == "gas")
1955
161
      solAssert(false, "Gas has been removed.");
1956
161
    else if (member == "blockhash")
1957
161
      solAssert(false, "Blockhash has been removed.");
1958
161
    else if (member == "creationCode" || member == "runtimeCode")
1959
13
    {
1960
13
      Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
1961
13
      auto const& contractType = dynamic_cast<ContractType const&>(*arg);
1962
13
      solAssert(!contractType.isSuper(), "");
1963
13
      ContractDefinition const& contract = contractType.contractDefinition();
1964
13
      utils().fetchFreeMemoryPointer();
1965
13
      m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
1966
13
      utils().copyContractCodeToMemory(contract, member == "creationCode");
1967
      // Stack: start end
1968
13
      m_context.appendInlineAssembly(
1969
13
        Whiskers(R"({
1970
13
          mstore(start, sub(end, add(start, 0x20)))
1971
13
          mstore(<free>, and(add(end, 31), not(31)))
1972
13
        })")("free", std::to_string(CompilerUtils::freeMemoryPointer)).render(),
1973
13
        {"start", "end"}
1974
13
      );
1975
13
      m_context << Instruction::POP;
1976
13
    }
1977
148
    else if (member == "name")
1978
17
    {
1979
17
      Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
1980
17
      auto const& contractType = dynamic_cast<ContractType const&>(*arg);
1981
17
      ContractDefinition const& contract = contractType.isSuper() ?
1982
0
        *contractType.contractDefinition().superContract(m_context.mostDerivedContract()) :
1983
17
        dynamic_cast<ContractType const&>(*arg).contractDefinition();
1984
17
      utils().allocateMemory(((contract.name().length() + 31) / 32) * 32 + 32);
1985
      // store string length
1986
17
      m_context << u256(contract.name().length()) << Instruction::DUP2 << Instruction::MSTORE;
1987
      // adjust pointer
1988
17
      m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
1989
17
      utils().storeStringData(contract.name());
1990
17
    }
1991
131
    else if (member == "interfaceId")
1992
6
    {
1993
6
      Type const* arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
1994
6
      ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
1995
6
      m_context << (u256{contract.interfaceId()} << (256 - 32));
1996
6
    }
1997
125
    else if (member == "min" || member == "max")
1998
92
    {
1999
92
      MagicType const* arg = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type);
2000
92
      if (IntegerType const* integerType = dynamic_cast<IntegerType const*>(arg->typeArgument()))
2001
88
        m_context << (member == "min" ? integerType->min() : integerType->max());
2002
4
      else if (EnumType const* enumType = dynamic_cast<EnumType const*>(arg->typeArgument()))
2003
4
        m_context << (member == "min" ? enumType->minValue() : enumType->maxValue());
2004
0
      else
2005
4
        solAssert(false, "min/max not available for the given type.");
2006
2007
92
    }
2008
33
    else if ((std::set<std::string>{"encode", "encodePacked", "encodeWithSelector", "encodeWithSignature", "decode"}).count(member))
2009
33
    {
2010
      // no-op
2011
33
    }
2012
0
    else
2013
33
      solAssert(false, "Unknown magic member.");
2014
582
    break;
2015
177k
  case Type::Category::Struct:
2016
177k
  {
2017
177k
    StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.expression().annotation().type);
2018
177k
    Type const* memberType = _memberAccess.annotation().type;
2019
177k
    switch (type.location())
2020
177k
    {
2021
43.2k
    case DataLocation::Storage:
2022
43.2k
    {
2023
43.2k
      std::pair<u256, unsigned> const& offsets = type.storageOffsetsOfMember(member);
2024
43.2k
      m_context << offsets.first << Instruction::ADD << u256(offsets.second);
2025
43.2k
      setLValueToStorageItem(_memberAccess);
2026
43.2k
      break;
2027
0
    }
2028
117k
    case DataLocation::Memory:
2029
117k
    {
2030
117k
      m_context << type.memoryOffsetOfMember(member) << Instruction::ADD;
2031
117k
      setLValue<MemoryItem>(_memberAccess, *memberType);
2032
117k
      break;
2033
0
    }
2034
16.1k
    case DataLocation::CallData:
2035
16.1k
    {
2036
16.1k
      if (_memberAccess.annotation().type->isDynamicallyEncoded())
2037
8.98k
      {
2038
8.98k
        m_context << Instruction::DUP1;
2039
8.98k
        m_context << type.calldataOffsetOfMember(member) << Instruction::ADD;
2040
8.98k
        CompilerUtils(m_context).accessCalldataTail(*memberType);
2041
8.98k
      }
2042
7.13k
      else
2043
7.13k
      {
2044
7.13k
        m_context << type.calldataOffsetOfMember(member) << Instruction::ADD;
2045
        // For non-value types the calldata offset is returned directly.
2046
7.13k
        if (memberType->isValueType())
2047
3.43k
        {
2048
3.43k
          solAssert(memberType->calldataEncodedSize() > 0, "");
2049
3.43k
          solAssert(memberType->storageBytes() <= 32, "");
2050
3.43k
          if (memberType->storageBytes() < 32 && m_context.useABICoderV2())
2051
3.37k
          {
2052
3.37k
            m_context << u256(32);
2053
3.37k
            CompilerUtils(m_context).abiDecodeV2({memberType}, false);
2054
3.37k
          }
2055
63
          else
2056
63
            CompilerUtils(m_context).loadFromMemoryDynamic(*memberType, true, true, false);
2057
3.43k
        }
2058
3.69k
        else
2059
7.13k
          solAssert(
2060
7.13k
            memberType->category() == Type::Category::Array ||
2061
7.13k
            memberType->category() == Type::Category::Struct,
2062
7.13k
            ""
2063
7.13k
          );
2064
7.13k
      }
2065
16.1k
      break;
2066
16.1k
    }
2067
16.1k
    default:
2068
0
      solAssert(false, "Illegal data location for struct.");
2069
177k
    }
2070
177k
    break;
2071
177k
  }
2072
177k
  case Type::Category::Enum:
2073
0
  {
2074
0
    EnumType const& type = dynamic_cast<EnumType const&>(*_memberAccess.expression().annotation().type);
2075
0
    m_context << type.memberValue(_memberAccess.memberName());
2076
0
    break;
2077
177k
  }
2078
9.68k
  case Type::Category::Array:
2079
9.68k
  {
2080
9.68k
    auto const& type = dynamic_cast<ArrayType const&>(*_memberAccess.expression().annotation().type);
2081
9.68k
    if (member == "length")
2082
9.68k
    {
2083
9.68k
      if (!type.isDynamicallySized())
2084
1.57k
      {
2085
1.57k
        utils().popStackElement(type);
2086
1.57k
        m_context << type.length();
2087
1.57k
      }
2088
8.11k
      else
2089
8.11k
        switch (type.location())
2090
8.11k
        {
2091
924
        case DataLocation::CallData:
2092
924
          m_context << Instruction::SWAP1 << Instruction::POP;
2093
924
          break;
2094
416
        case DataLocation::Storage:
2095
416
          ArrayUtils(m_context).retrieveLength(type);
2096
416
          m_context << Instruction::SWAP1 << Instruction::POP;
2097
416
          break;
2098
0
        case DataLocation::Transient:
2099
0
          solUnimplemented("Transient data location is only supported for value types.");
2100
0
          break;
2101
6.77k
        case DataLocation::Memory:
2102
6.77k
          m_context << Instruction::MLOAD;
2103
6.77k
          break;
2104
8.11k
        }
2105
9.68k
    }
2106
0
    else if (member == "push" || member == "pop")
2107
0
    {
2108
0
      solAssert(
2109
0
        type.isDynamicallySized() &&
2110
0
        type.location() == DataLocation::Storage &&
2111
0
        type.category() == Type::Category::Array,
2112
0
        "Tried to use ." + member + "() on a non-dynamically sized array"
2113
0
      );
2114
0
    }
2115
0
    else
2116
0
      solAssert(false, "Illegal array member.");
2117
9.68k
    break;
2118
9.68k
  }
2119
9.68k
  case Type::Category::FixedBytes:
2120
17
  {
2121
17
    auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type);
2122
17
    utils().popStackElement(type);
2123
17
    if (member == "length")
2124
17
      m_context << u256(type.numBytes());
2125
0
    else
2126
17
      solAssert(false, "Illegal fixed bytes member.");
2127
17
    break;
2128
17
  }
2129
32
  case Type::Category::Module:
2130
32
  {
2131
32
    Type::Category category = _memberAccess.annotation().type->category();
2132
32
    solAssert(
2133
32
      dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration) ||
2134
32
      dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration) ||
2135
32
      dynamic_cast<ErrorDefinition const*>(_memberAccess.annotation().referencedDeclaration) ||
2136
32
      category == Type::Category::TypeType ||
2137
32
      category == Type::Category::Module,
2138
32
      ""
2139
32
    );
2140
32
    if (auto variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
2141
3
    {
2142
3
      solAssert(variable->isConstant(), "");
2143
3
      appendVariable(*variable, static_cast<Expression const&>(_memberAccess));
2144
3
    }
2145
29
    else if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration))
2146
16
    {
2147
16
      auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
2148
16
      solAssert(function && function->isFree(), "");
2149
16
      solAssert(funType->kind() == FunctionType::Kind::Internal, "");
2150
16
      solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
2151
16
      utils().pushCombinedFunctionEntryLabel(
2152
16
        *function,
2153
        // If we call directly, do not include the second label.
2154
16
        !_memberAccess.annotation().calledDirectly
2155
16
      );
2156
16
    }
2157
13
    else if (auto const* contract = dynamic_cast<ContractDefinition const*>(_memberAccess.annotation().referencedDeclaration))
2158
4
    {
2159
4
      if (contract->isLibrary())
2160
2
        m_context.appendLibraryAddress(contract->fullyQualifiedName());
2161
4
    }
2162
32
    break;
2163
32
  }
2164
32
  default:
2165
0
    solAssert(false, "Member access to unknown type.");
2166
191k
  }
2167
191k
  return false;
2168
191k
}
2169
2170
bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
2171
143k
{
2172
143k
  CompilerContext::LocationSetter locationSetter(m_context, _indexAccess);
2173
143k
  _indexAccess.baseExpression().accept(*this);
2174
2175
143k
  Type const& baseType = *_indexAccess.baseExpression().annotation().type;
2176
2177
143k
  switch (baseType.category())
2178
143k
  {
2179
712
    case Type::Category::Mapping:
2180
712
    {
2181
      // stack: storage_base_ref
2182
712
      Type const* keyType = dynamic_cast<MappingType const&>(baseType).keyType();
2183
712
      solAssert(_indexAccess.indexExpression(), "Index expression expected.");
2184
712
      if (keyType->isDynamicallySized())
2185
75
      {
2186
75
        _indexAccess.indexExpression()->accept(*this);
2187
75
        utils().fetchFreeMemoryPointer();
2188
        // stack: base index mem
2189
        // note: the following operations must not allocate memory!
2190
75
        utils().packedEncode(
2191
75
          TypePointers{_indexAccess.indexExpression()->annotation().type},
2192
75
          TypePointers{keyType}
2193
75
        );
2194
75
        m_context << Instruction::SWAP1;
2195
75
        utils().storeInMemoryDynamic(*TypeProvider::uint256());
2196
75
        utils().toSizeAfterFreeMemoryPointer();
2197
75
      }
2198
637
      else
2199
637
      {
2200
637
        m_context << u256(0); // memory position
2201
637
        appendExpressionCopyToMemory(*keyType, *_indexAccess.indexExpression());
2202
637
        m_context << Instruction::SWAP1;
2203
637
        solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
2204
637
        utils().storeInMemoryDynamic(*TypeProvider::uint256());
2205
637
        m_context << u256(0);
2206
637
      }
2207
712
      m_context << Instruction::KECCAK256;
2208
712
      m_context << u256(0);
2209
712
      setLValueToStorageItem(_indexAccess);
2210
712
      break;
2211
712
    }
2212
102
    case Type::Category::ArraySlice:
2213
102
    {
2214
102
      auto const& arrayType = dynamic_cast<ArraySliceType const&>(baseType).arrayType();
2215
102
      solAssert(
2216
102
        arrayType.location() == DataLocation::CallData &&
2217
102
        arrayType.isDynamicallySized() &&
2218
102
        !arrayType.baseType()->isDynamicallyEncoded(),
2219
102
        ""
2220
102
      );
2221
102
      solAssert(_indexAccess.indexExpression(), "Index expression expected.");
2222
2223
102
      acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
2224
102
      ArrayUtils(m_context).accessCallDataArrayElement(arrayType);
2225
102
      break;
2226
2227
102
    }
2228
141k
    case Type::Category::Array:
2229
141k
    {
2230
141k
      ArrayType const& arrayType = dynamic_cast<ArrayType const&>(baseType);
2231
141k
      solAssert(_indexAccess.indexExpression(), "Index expression expected.");
2232
2233
141k
      acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
2234
      // stack layout: <base_ref> [<length>] <index>
2235
141k
      switch (arrayType.location())
2236
141k
      {
2237
37.0k
        case DataLocation::Storage:
2238
37.0k
          ArrayUtils(m_context).accessIndex(arrayType);
2239
37.0k
          if (arrayType.isByteArrayOrString())
2240
555
          {
2241
555
            solAssert(!arrayType.isString(), "Index access to string is not allowed.");
2242
555
            setLValue<StorageByteArrayElement>(_indexAccess);
2243
555
          }
2244
36.4k
          else
2245
36.4k
            setLValueToStorageItem(_indexAccess);
2246
37.0k
          break;
2247
37.0k
        case DataLocation::Transient:
2248
0
          solUnimplemented("Transient data location is only supported for value types.");
2249
0
          break;
2250
97.8k
        case DataLocation::Memory:
2251
97.8k
          ArrayUtils(m_context).accessIndex(arrayType);
2252
97.8k
          setLValue<MemoryItem>(_indexAccess, *_indexAccess.annotation().type, !arrayType.isByteArrayOrString());
2253
97.8k
          break;
2254
6.86k
        case DataLocation::CallData:
2255
6.86k
          ArrayUtils(m_context).accessCallDataArrayElement(arrayType);
2256
6.86k
          break;
2257
141k
      }
2258
141k
      break;
2259
141k
    }
2260
141k
    case Type::Category::FixedBytes:
2261
678
    {
2262
678
      FixedBytesType const& fixedBytesType = dynamic_cast<FixedBytesType const&>(baseType);
2263
678
      solAssert(_indexAccess.indexExpression(), "Index expression expected.");
2264
2265
678
      acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
2266
      // stack layout: <value> <index>
2267
      // check out-of-bounds access
2268
678
      m_context << u256(fixedBytesType.numBytes());
2269
678
      m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO;
2270
      // out-of-bounds access throws exception
2271
678
      m_context.appendConditionalPanic(util::PanicCode::ArrayOutOfBounds);
2272
2273
678
      m_context << Instruction::BYTE;
2274
678
      utils().leftShiftNumberOnStack(256 - 8);
2275
678
      break;
2276
678
    }
2277
24
    case Type::Category::TypeType:
2278
24
    {
2279
24
      solAssert(baseType.sizeOnStack() == 0, "");
2280
24
      solAssert(_indexAccess.annotation().type->sizeOnStack() == 0, "");
2281
      // no-op - this seems to be a lone array type (`structType[];`)
2282
24
      break;
2283
24
    }
2284
24
    default:
2285
0
      solAssert(false, "Index access only allowed for mappings or arrays.");
2286
0
      break;
2287
143k
  }
2288
2289
143k
  return false;
2290
143k
}
2291
2292
bool ExpressionCompiler::visit(IndexRangeAccess const& _indexAccess)
2293
351
{
2294
351
  CompilerContext::LocationSetter locationSetter(m_context, _indexAccess);
2295
351
  _indexAccess.baseExpression().accept(*this);
2296
  // stack: offset length
2297
2298
351
  Type const& baseType = *_indexAccess.baseExpression().annotation().type;
2299
2300
351
  ArrayType const *arrayType = dynamic_cast<ArrayType const*>(&baseType);
2301
351
  if (!arrayType)
2302
117
    if (ArraySliceType const* sliceType = dynamic_cast<ArraySliceType const*>(&baseType))
2303
117
      arrayType = &sliceType->arrayType();
2304
2305
351
  solAssert(arrayType, "");
2306
351
  solUnimplementedAssert(
2307
351
    arrayType->location() == DataLocation::CallData &&
2308
351
    arrayType->isDynamicallySized() &&
2309
351
    !arrayType->baseType()->isDynamicallyEncoded()
2310
351
  );
2311
2312
351
  if (_indexAccess.startExpression())
2313
319
    acceptAndConvert(*_indexAccess.startExpression(), *TypeProvider::uint256());
2314
32
  else
2315
32
    m_context << u256(0);
2316
  // stack: offset length sliceStart
2317
2318
351
  m_context << Instruction::SWAP1;
2319
  // stack: offset sliceStart length
2320
2321
351
  if (_indexAccess.endExpression())
2322
197
    acceptAndConvert(*_indexAccess.endExpression(), *TypeProvider::uint256());
2323
154
  else
2324
154
    m_context << Instruction::DUP1;
2325
  // stack: offset sliceStart length sliceEnd
2326
2327
351
  m_context << Instruction::SWAP3;
2328
  // stack: sliceEnd sliceStart length offset
2329
2330
351
  m_context.callYulFunction(m_context.utilFunctions().calldataArrayIndexRangeAccess(*arrayType), 4, 2);
2331
2332
351
  return false;
2333
351
}
2334
2335
void ExpressionCompiler::endVisit(Identifier const& _identifier)
2336
134k
{
2337
134k
  CompilerContext::LocationSetter locationSetter(m_context, _identifier);
2338
134k
  Declaration const* declaration = _identifier.annotation().referencedDeclaration;
2339
134k
  if (MagicVariableDeclaration const* magicVar = dynamic_cast<MagicVariableDeclaration const*>(declaration))
2340
4.34k
  {
2341
4.34k
    switch (magicVar->type()->category())
2342
4.34k
    {
2343
3.69k
    case Type::Category::Contract:
2344
3.69k
      if (dynamic_cast<ContractType const*>(magicVar->type()))
2345
3.69k
      {
2346
3.69k
        solAssert(_identifier.name() == "this", "");
2347
3.69k
        m_context << Instruction::ADDRESS;
2348
3.69k
      }
2349
3.69k
      break;
2350
3.69k
    default:
2351
653
      break;
2352
4.34k
    }
2353
4.34k
  }
2354
129k
  else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
2355
10.4k
  {
2356
10.4k
    solAssert(*_identifier.annotation().requiredLookup == VirtualLookup::Virtual, "");
2357
10.4k
    utils().pushCombinedFunctionEntryLabel(
2358
10.4k
      functionDef->resolveVirtual(m_context.mostDerivedContract()),
2359
      // If we call directly, do not include the second (potential runtime) label.
2360
      // Including the label might lead to the runtime code being included in the creation
2361
      // code even though it is never executed.
2362
10.4k
      !_identifier.annotation().calledDirectly
2363
10.4k
    );
2364
10.4k
  }
2365
119k
  else if (auto variable = dynamic_cast<VariableDeclaration const*>(declaration))
2366
118k
    appendVariable(*variable, static_cast<Expression const&>(_identifier));
2367
725
  else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
2368
132
  {
2369
132
    if (contract->isLibrary())
2370
125
      m_context.appendLibraryAddress(contract->fullyQualifiedName());
2371
132
  }
2372
593
  else if (dynamic_cast<EventDefinition const*>(declaration))
2373
430
  {
2374
    // no-op
2375
430
  }
2376
163
  else if (dynamic_cast<ErrorDefinition const*>(declaration))
2377
42
  {
2378
    // no-op
2379
42
  }
2380
121
  else if (dynamic_cast<EnumDefinition const*>(declaration))
2381
65
  {
2382
    // no-op
2383
65
  }
2384
56
  else if (dynamic_cast<UserDefinedValueTypeDefinition const*>(declaration))
2385
17
  {
2386
    // no-op
2387
17
  }
2388
39
  else if (dynamic_cast<StructDefinition const*>(declaration))
2389
8
  {
2390
    // no-op
2391
8
  }
2392
31
  else if (dynamic_cast<ImportDirective const*>(declaration))
2393
31
  {
2394
    // no-op
2395
31
  }
2396
0
  else
2397
0
  {
2398
0
    solAssert(false, "Identifier type not expected in expression context.");
2399
0
  }
2400
134k
}
2401
2402
void ExpressionCompiler::endVisit(Literal const& _literal)
2403
279k
{
2404
279k
  CompilerContext::LocationSetter locationSetter(m_context, _literal);
2405
279k
  Type const* type = _literal.annotation().type;
2406
2407
279k
  switch (type->category())
2408
279k
  {
2409
235k
  case Type::Category::RationalNumber:
2410
253k
  case Type::Category::Bool:
2411
253k
  case Type::Category::Address:
2412
253k
    m_context << type->literalValue(&_literal);
2413
253k
    break;
2414
25.3k
  case Type::Category::StringLiteral:
2415
25.3k
    break; // will be done during conversion
2416
0
  default:
2417
0
    solUnimplemented("Only integer, boolean and string literals implemented for now.");
2418
279k
  }
2419
279k
}
2420
2421
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation)
2422
592
{
2423
592
  Token const c_op = _binaryOperation.getOperator();
2424
592
  solAssert(c_op == Token::Or || c_op == Token::And, "");
2425
2426
592
  _binaryOperation.leftExpression().accept(*this);
2427
592
  m_context << Instruction::DUP1;
2428
592
  if (c_op == Token::And)
2429
90
    m_context << Instruction::ISZERO;
2430
592
  evmasm::AssemblyItem endLabel = m_context.appendConditionalJump();
2431
592
  m_context << Instruction::POP;
2432
592
  _binaryOperation.rightExpression().accept(*this);
2433
592
  m_context << endLabel;
2434
592
}
2435
2436
void ExpressionCompiler::appendCompareOperatorCode(Token _operator, Type const& _type)
2437
44.9k
{
2438
44.9k
  if (_operator == Token::Equal || _operator == Token::NotEqual)
2439
40.4k
  {
2440
40.4k
    FunctionType const* functionType = dynamic_cast<decltype(functionType)>(&_type);
2441
40.4k
    if (functionType && functionType->kind() == FunctionType::Kind::External)
2442
16
    {
2443
16
      solUnimplementedAssert(functionType->sizeOnStack() == 2, "");
2444
16
      m_context << Instruction::SWAP3;
2445
2446
16
      m_context << ((u256(1) << 160) - 1) << Instruction::AND;
2447
16
      m_context << Instruction::SWAP1;
2448
16
      m_context << ((u256(1) << 160) - 1) << Instruction::AND;
2449
16
      m_context << Instruction::EQ;
2450
16
      m_context << Instruction::SWAP2;
2451
16
      m_context << ((u256(1) << 32) - 1) << Instruction::AND;
2452
16
      m_context << Instruction::SWAP1;
2453
16
      m_context << ((u256(1) << 32) - 1) << Instruction::AND;
2454
16
      m_context << Instruction::EQ;
2455
16
      m_context << Instruction::AND;
2456
16
    }
2457
40.4k
    else
2458
40.4k
    {
2459
40.4k
      solAssert(_type.sizeOnStack() == 1, "Comparison of multi-slot types.");
2460
40.4k
      if (functionType && functionType->kind() == FunctionType::Kind::Internal)
2461
14
      {
2462
        // We have to remove the upper bits (construction time value) because they might
2463
        // be "unknown" in one of the operands and not in the other.
2464
14
        m_context << ((u256(1) << 32) - 1) << Instruction::AND;
2465
14
        m_context << Instruction::SWAP1;
2466
14
        m_context << ((u256(1) << 32) - 1) << Instruction::AND;
2467
14
      }
2468
40.4k
      m_context << Instruction::EQ;
2469
40.4k
    }
2470
40.4k
    if (_operator == Token::NotEqual)
2471
37.7k
      m_context << Instruction::ISZERO;
2472
40.4k
  }
2473
4.44k
  else
2474
4.44k
  {
2475
4.44k
    solAssert(_type.sizeOnStack() == 1, "Comparison of multi-slot types.");
2476
4.44k
    bool isSigned = false;
2477
4.44k
    if (auto type = dynamic_cast<IntegerType const*>(&_type))
2478
4.41k
      isSigned = type->isSigned();
2479
2480
4.44k
    switch (_operator)
2481
4.44k
    {
2482
135
    case Token::GreaterThanOrEqual:
2483
135
      m_context <<
2484
135
        (isSigned ? Instruction::SLT : Instruction::LT) <<
2485
135
        Instruction::ISZERO;
2486
135
      break;
2487
134
    case Token::LessThanOrEqual:
2488
134
      m_context <<
2489
134
        (isSigned ? Instruction::SGT : Instruction::GT) <<
2490
134
        Instruction::ISZERO;
2491
134
      break;
2492
517
    case Token::GreaterThan:
2493
517
      m_context << (isSigned ? Instruction::SGT : Instruction::GT);
2494
517
      break;
2495
3.66k
    case Token::LessThan:
2496
3.66k
      m_context << (isSigned ? Instruction::SLT : Instruction::LT);
2497
3.66k
      break;
2498
0
    default:
2499
0
      solAssert(false, "Unknown comparison operator.");
2500
4.44k
    }
2501
4.44k
  }
2502
44.9k
}
2503
2504
void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token _operator, Type const& _type)
2505
7.06k
{
2506
7.06k
  if (TokenTraits::isArithmeticOp(_operator))
2507
6.77k
    appendArithmeticOperatorCode(_operator, _type);
2508
289
  else if (TokenTraits::isBitOp(_operator))
2509
289
    appendBitOperatorCode(_operator);
2510
0
  else
2511
289
    solAssert(false, "Unknown binary operator.");
2512
7.06k
}
2513
2514
void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type const& _type)
2515
6.77k
{
2516
6.77k
  if (_type.category() == Type::Category::FixedPoint)
2517
6.77k
    solUnimplemented("Not yet implemented - FixedPointType.");
2518
2519
6.77k
  IntegerType const& type = dynamic_cast<IntegerType const&>(_type);
2520
6.77k
  if (m_context.arithmetic() == Arithmetic::Checked)
2521
6.68k
  {
2522
6.68k
    std::string functionName;
2523
6.68k
    switch (_operator)
2524
6.68k
    {
2525
2.36k
    case Token::Add:
2526
2.36k
      functionName = m_context.utilFunctions().overflowCheckedIntAddFunction(type);
2527
2.36k
      break;
2528
1.21k
    case Token::Sub:
2529
1.21k
      functionName = m_context.utilFunctions().overflowCheckedIntSubFunction(type);
2530
1.21k
      break;
2531
2.13k
    case Token::Mul:
2532
2.13k
      functionName = m_context.utilFunctions().overflowCheckedIntMulFunction(type);
2533
2.13k
      break;
2534
238
    case Token::Div:
2535
238
      functionName = m_context.utilFunctions().overflowCheckedIntDivFunction(type);
2536
238
      break;
2537
731
    case Token::Mod:
2538
731
      functionName = m_context.utilFunctions().intModFunction(type);
2539
731
      break;
2540
0
    case Token::Exp:
2541
      // EXP is handled in a different function.
2542
0
    default:
2543
0
      solAssert(false, "Unknown arithmetic operator.");
2544
6.68k
    }
2545
    // TODO Maybe we want to force-inline this?
2546
6.68k
    m_context.callYulFunction(functionName, 2, 1);
2547
6.68k
  }
2548
92
  else
2549
92
  {
2550
92
    bool const c_isSigned = type.isSigned();
2551
2552
92
    switch (_operator)
2553
92
    {
2554
37
    case Token::Add:
2555
37
      m_context << Instruction::ADD;
2556
37
      break;
2557
31
    case Token::Sub:
2558
31
      m_context << Instruction::SUB;
2559
31
      break;
2560
17
    case Token::Mul:
2561
17
      m_context << Instruction::MUL;
2562
17
      break;
2563
5
    case Token::Div:
2564
7
    case Token::Mod:
2565
7
    {
2566
      // Test for division by zero
2567
7
      m_context << Instruction::DUP2 << Instruction::ISZERO;
2568
7
      m_context.appendConditionalPanic(util::PanicCode::DivisionByZero);
2569
2570
7
      if (_operator == Token::Div)
2571
5
        m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
2572
2
      else
2573
2
        m_context << (c_isSigned ? Instruction::SMOD : Instruction::MOD);
2574
7
      break;
2575
5
    }
2576
0
    default:
2577
0
      solAssert(false, "Unknown arithmetic operator.");
2578
92
    }
2579
92
  }
2580
6.77k
}
2581
2582
void ExpressionCompiler::appendBitOperatorCode(Token _operator)
2583
289
{
2584
289
  switch (_operator)
2585
289
  {
2586
85
  case Token::BitOr:
2587
85
    m_context << Instruction::OR;
2588
85
    break;
2589
95
  case Token::BitAnd:
2590
95
    m_context << Instruction::AND;
2591
95
    break;
2592
109
  case Token::BitXor:
2593
109
    m_context << Instruction::XOR;
2594
109
    break;
2595
0
  default:
2596
0
    solAssert(false, "Unknown bit operator.");
2597
289
  }
2598
289
}
2599
2600
void ExpressionCompiler::appendShiftOperatorCode(Token _operator, Type const& _valueType, Type const& _shiftAmountType)
2601
109
{
2602
  // stack: shift_amount value_to_shift
2603
2604
109
  bool c_valueSigned = false;
2605
109
  if (auto valueType = dynamic_cast<IntegerType const*>(&_valueType))
2606
83
    c_valueSigned = valueType->isSigned();
2607
26
  else
2608
109
    solAssert(dynamic_cast<FixedBytesType const*>(&_valueType), "Only integer and fixed bytes type supported for shifts.");
2609
2610
  // The amount can be a RationalNumberType too.
2611
109
  if (auto amountType = dynamic_cast<RationalNumberType const*>(&_shiftAmountType))
2612
0
  {
2613
    // This should be handled by the type checker.
2614
0
    solAssert(amountType->integerType(), "");
2615
0
    solAssert(!amountType->integerType()->isSigned(), "");
2616
0
  }
2617
109
  else if (auto amountType = dynamic_cast<IntegerType const*>(&_shiftAmountType))
2618
109
    solAssert(!amountType->isSigned(), "");
2619
0
  else
2620
109
    solAssert(false, "Invalid shift amount type.");
2621
2622
109
  m_context << Instruction::SWAP1;
2623
  // stack: value_to_shift shift_amount
2624
2625
109
  switch (_operator)
2626
109
  {
2627
53
  case Token::SHL:
2628
53
    if (m_context.evmVersion().hasBitwiseShifting())
2629
32
      m_context << Instruction::SHL;
2630
21
    else
2631
21
      m_context << u256(2) << Instruction::EXP << Instruction::MUL;
2632
53
    break;
2633
56
  case Token::SAR:
2634
56
    if (m_context.evmVersion().hasBitwiseShifting())
2635
33
      m_context << (c_valueSigned ? Instruction::SAR : Instruction::SHR);
2636
23
    else
2637
23
    {
2638
23
      if (c_valueSigned)
2639
        // In the following assembly snippet, xor_mask will be zero, if value_to_shift is positive.
2640
        // Therefore xor'ing with xor_mask is the identity and the computation reduces to
2641
        // div(value_to_shift, exp(2, shift_amount)), which is correct, since for positive values
2642
        // arithmetic right shift is dividing by a power of two (which, as a bitwise operation, results
2643
        // in discarding bits on the right and filling with zeros from the left).
2644
        // For negative values arithmetic right shift, viewed as a bitwise operation, discards bits to the
2645
        // right and fills in ones from the left. This is achieved as follows:
2646
        // If value_to_shift is negative, then xor_mask will have all bits set, so xor'ing with xor_mask
2647
        // will flip all bits. First all bits in value_to_shift are flipped. As for the positive case,
2648
        // dividing by a power of two using integer arithmetic results in discarding bits to the right
2649
        // and filling with zeros from the left. Flipping all bits in the result again, turns all zeros
2650
        // on the left to ones and restores the non-discarded, shifted bits to their original value (they
2651
        // have now been flipped twice). In summary we now have discarded bits to the right and filled with
2652
        // ones from the left, i.e. we have performed an arithmetic right shift.
2653
4
        m_context.appendInlineAssembly(R"({
2654
4
          let xor_mask := sub(0, slt(value_to_shift, 0))
2655
4
          value_to_shift := xor(div(xor(value_to_shift, xor_mask), exp(2, shift_amount)), xor_mask)
2656
4
        })", {"value_to_shift", "shift_amount"});
2657
19
      else
2658
19
        m_context.appendInlineAssembly(R"({
2659
19
          value_to_shift := div(value_to_shift, exp(2, shift_amount))
2660
19
        })", {"value_to_shift", "shift_amount"});
2661
23
      m_context << Instruction::POP;
2662
2663
23
    }
2664
56
    break;
2665
0
  case Token::SHR:
2666
0
  default:
2667
0
    solAssert(false, "Unknown shift operator.");
2668
109
  }
2669
109
}
2670
2671
void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type const& _exponentType)
2672
617
{
2673
617
  solAssert(_valueType.category() == Type::Category::Integer, "");
2674
617
  solAssert(!dynamic_cast<IntegerType const&>(_exponentType).isSigned(), "");
2675
2676
2677
617
  if (m_context.arithmetic() == Arithmetic::Checked)
2678
586
    m_context.callYulFunction(m_context.utilFunctions().overflowCheckedIntExpFunction(
2679
586
      dynamic_cast<IntegerType const&>(_valueType),
2680
586
      dynamic_cast<IntegerType const&>(_exponentType)
2681
586
    ), 2, 1);
2682
31
  else
2683
31
    m_context << Instruction::EXP;
2684
617
}
2685
2686
void ExpressionCompiler::appendExternalFunctionCall(
2687
  FunctionType const& _functionType,
2688
  std::vector<ASTPointer<Expression const>> const& _arguments,
2689
  bool _tryCall
2690
)
2691
3.39k
{
2692
3.39k
  solAssert(
2693
3.39k
    _functionType.takesArbitraryParameters() ||
2694
3.39k
    _arguments.size() == _functionType.parameterTypes().size(), ""
2695
3.39k
  );
2696
2697
  // Assumed stack content here:
2698
  // <stack top>
2699
  // value [if _functionType.valueSet()]
2700
  // gas [if _functionType.gasSet()]
2701
  // self object [if bound - moved to top right away]
2702
  // function identifier [unless bare]
2703
  // contract address
2704
2705
3.39k
  unsigned selfSize = _functionType.hasBoundFirstArgument() ? _functionType.selfType()->sizeOnStack() : 0;
2706
3.39k
  unsigned gasValueSize = (_functionType.gasSet() ? 1u : 0u) + (_functionType.valueSet() ? 1u : 0u);
2707
3.39k
  unsigned contractStackPos = m_context.currentToBaseStackOffset(1 + gasValueSize + selfSize + (_functionType.isBareCall() ? 0 : 1));
2708
3.39k
  unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize);
2709
3.39k
  unsigned valueStackPos = m_context.currentToBaseStackOffset(1);
2710
2711
  // move self object to top
2712
3.39k
  if (_functionType.hasBoundFirstArgument())
2713
43
    utils().moveToStackTop(gasValueSize, _functionType.selfType()->sizeOnStack());
2714
2715
3.39k
  auto funKind = _functionType.kind();
2716
2717
3.39k
  solAssert(funKind != FunctionType::Kind::BareStaticCall || m_context.evmVersion().hasStaticCall(), "");
2718
2719
3.39k
  solAssert(funKind != FunctionType::Kind::BareCallCode, "Callcode has been removed.");
2720
2721
3.39k
  bool returnSuccessConditionAndReturndata = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall;
2722
3.39k
  bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
2723
3.39k
  bool useStaticCall = funKind == FunctionType::Kind::BareStaticCall || (_functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall());
2724
2725
3.39k
  if (_tryCall)
2726
72
  {
2727
72
    solAssert(!returnSuccessConditionAndReturndata, "");
2728
72
    solAssert(!_functionType.isBareCall(), "");
2729
72
  }
2730
2731
3.39k
  ReturnInfo const returnInfo{m_context.evmVersion(), _functionType};
2732
3.39k
  bool const haveReturndatacopy = m_context.evmVersion().supportsReturndata();
2733
3.39k
  unsigned const retSize = returnInfo.estimatedReturnSize;
2734
3.39k
  bool const dynamicReturnSize = returnInfo.dynamicReturnSize;
2735
3.39k
  TypePointers const& returnTypes = returnInfo.returnTypes;
2736
2737
  // Evaluate arguments.
2738
3.39k
  TypePointers argumentTypes;
2739
3.39k
  TypePointers parameterTypes = _functionType.parameterTypes();
2740
3.39k
  if (_functionType.hasBoundFirstArgument())
2741
43
  {
2742
43
    argumentTypes.push_back(_functionType.selfType());
2743
43
    parameterTypes.insert(parameterTypes.begin(), _functionType.selfType());
2744
43
  }
2745
7.23k
  for (size_t i = 0; i < _arguments.size(); ++i)
2746
3.83k
  {
2747
3.83k
    _arguments[i]->accept(*this);
2748
3.83k
    argumentTypes.push_back(_arguments[i]->annotation().type);
2749
3.83k
  }
2750
2751
3.39k
  if (funKind == FunctionType::Kind::ECRecover)
2752
10
  {
2753
    // Clears 32 bytes of currently free memory and advances free memory pointer.
2754
    // Output area will be "start of input area" - 32.
2755
    // The reason is that a failing ECRecover cannot be detected, it will just return
2756
    // zero bytes (which we cannot detect).
2757
10
    solAssert(0 < retSize && retSize <= 32, "");
2758
10
    utils().fetchFreeMemoryPointer();
2759
10
    m_context << u256(0) << Instruction::DUP2 << Instruction::MSTORE;
2760
10
    m_context << u256(32) << Instruction::ADD;
2761
10
    utils().storeFreeMemoryPointer();
2762
10
  }
2763
2764
3.39k
  if (!m_context.evmVersion().canOverchargeGasForCall())
2765
118
  {
2766
    // Touch the end of the output area so that we do not pay for memory resize during the call
2767
    // (which we would have to subtract from the gas left)
2768
    // We could also just use MLOAD; POP right before the gas calculation, but the optimizer
2769
    // would remove that, so we use MSTORE here.
2770
118
    if (!_functionType.gasSet() && retSize > 0)
2771
65
    {
2772
65
      m_context << u256(0);
2773
65
      utils().fetchFreeMemoryPointer();
2774
      // This touches too much, but that way we save some rounding arithmetic
2775
65
      m_context << u256(retSize) << Instruction::ADD << Instruction::MSTORE;
2776
65
    }
2777
118
  }
2778
2779
  // Copy function identifier to memory.
2780
3.39k
  utils().fetchFreeMemoryPointer();
2781
3.39k
  if (!_functionType.isBareCall())
2782
2.51k
  {
2783
2.51k
    m_context << dupInstruction(2 + gasValueSize + CompilerUtils::sizeOnStack(argumentTypes));
2784
2.51k
    utils().storeInMemoryDynamic(IntegerType(8 * CompilerUtils::dataStartOffset), false);
2785
2.51k
  }
2786
2787
  // If the function takes arbitrary parameters or is a bare call, copy dynamic length data in place.
2788
  // Move arguments to memory, will not update the free memory pointer (but will update the memory
2789
  // pointer on the stack).
2790
3.39k
  bool encodeInPlace = _functionType.takesArbitraryParameters() || _functionType.isBareCall();
2791
3.39k
  if (_functionType.kind() == FunctionType::Kind::ECRecover)
2792
    // This would be the only combination of padding and in-place encoding,
2793
    // but all parameters of ecrecover are value types anyway.
2794
10
    encodeInPlace = false;
2795
3.39k
  bool encodeForLibraryCall = funKind == FunctionType::Kind::DelegateCall;
2796
3.39k
  utils().encodeToMemory(
2797
3.39k
    argumentTypes,
2798
3.39k
    parameterTypes,
2799
3.39k
    _functionType.padArguments(),
2800
3.39k
    encodeInPlace,
2801
3.39k
    encodeForLibraryCall
2802
3.39k
  );
2803
2804
  // Stack now:
2805
  // <stack top>
2806
  // input_memory_end
2807
  // value [if _functionType.valueSet()]
2808
  // gas [if _functionType.gasSet()]
2809
  // function identifier [unless bare]
2810
  // contract address
2811
2812
  // Output data will replace input data, unless we have ECRecover (then, output
2813
  // area will be 32 bytes just before input area).
2814
  // put on stack: <size of output> <memory pos of output> <size of input> <memory pos of input>
2815
3.39k
  m_context << u256(retSize);
2816
3.39k
  utils().fetchFreeMemoryPointer(); // This is the start of input
2817
3.39k
  if (funKind == FunctionType::Kind::ECRecover)
2818
10
  {
2819
    // In this case, output is 32 bytes before input and has already been cleared.
2820
10
    m_context << u256(32) << Instruction::DUP2 << Instruction::SUB << Instruction::SWAP1;
2821
    // Here: <input end> <output size> <outpos> <input pos>
2822
10
    m_context << Instruction::DUP1 << Instruction::DUP5 << Instruction::SUB;
2823
10
    m_context << Instruction::SWAP1;
2824
10
  }
2825
3.38k
  else
2826
3.38k
  {
2827
3.38k
    m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::SUB;
2828
3.38k
    m_context << Instruction::DUP2;
2829
3.38k
  }
2830
2831
  // CALL arguments: outSize, outOff, inSize, inOff (already present up to here)
2832
  // [value,] addr, gas (stack top)
2833
3.39k
  if (isDelegateCall)
2834
3.39k
    solAssert(!_functionType.valueSet(), "Value set for delegatecall");
2835
3.24k
  else if (useStaticCall)
2836
3.24k
    solAssert(!_functionType.valueSet(), "Value set for staticcall");
2837
1.36k
  else if (_functionType.valueSet())
2838
86
    m_context << dupInstruction(m_context.baseToCurrentStackOffset(valueStackPos));
2839
1.27k
  else
2840
1.27k
    m_context << u256(0);
2841
3.39k
  m_context << dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos));
2842
2843
3.39k
  bool existenceChecked = false;
2844
  // Check the target contract exists (has code) for non-low-level calls.
2845
3.39k
  if (funKind == FunctionType::Kind::External || funKind == FunctionType::Kind::DelegateCall)
2846
2.51k
  {
2847
2.51k
    size_t encodedHeadSize = 0;
2848
2.51k
    for (auto const& t: returnTypes)
2849
2.44k
      encodedHeadSize += t->decodingType()->calldataHeadSize();
2850
    // We do not need to check extcodesize if we expect return data, since if there is no
2851
    // code, the call will return empty data and the ABI decoder will revert.
2852
2.51k
    if (
2853
2.51k
      encodedHeadSize == 0 ||
2854
2.51k
      !haveReturndatacopy ||
2855
2.51k
      m_context.revertStrings() >= RevertStrings::Debug
2856
2.51k
    )
2857
403
    {
2858
403
      m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO;
2859
403
      m_context.appendConditionalRevert(false, "Target contract does not contain code");
2860
403
      existenceChecked = true;
2861
403
    }
2862
2.51k
  }
2863
2864
3.39k
  if (_functionType.gasSet())
2865
79
    m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
2866
3.31k
  else if (m_context.evmVersion().canOverchargeGasForCall())
2867
    // Send all gas (requires tangerine whistle EVM)
2868
3.20k
    m_context << Instruction::GAS;
2869
114
  else
2870
114
  {
2871
    // send all gas except the amount needed to execute "SUB" and "CALL"
2872
    // @todo this retains too much gas for now, needs to be fine-tuned.
2873
114
    u256 gasNeededByCaller = evmasm::GasCosts::callGas(m_context.evmVersion()) + 10;
2874
114
    if (_functionType.valueSet())
2875
3
      gasNeededByCaller += evmasm::GasCosts::callValueTransferGas;
2876
114
    if (!existenceChecked)
2877
33
      gasNeededByCaller += evmasm::GasCosts::callNewAccountGas; // we never know
2878
114
    m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB;
2879
114
  }
2880
  // Order is important here, STATICCALL might overlap with DELEGATECALL.
2881
3.39k
  if (isDelegateCall)
2882
154
    m_context << Instruction::DELEGATECALL;
2883
3.24k
  else if (useStaticCall)
2884
1.88k
    m_context << Instruction::STATICCALL;
2885
1.36k
  else
2886
1.36k
    m_context << Instruction::CALL;
2887
2888
3.39k
  unsigned remainsSize =
2889
3.39k
    2u + // contract address, input_memory_end
2890
3.39k
    (_functionType.valueSet() ? 1 : 0) +
2891
3.39k
    (_functionType.gasSet() ? 1 : 0) +
2892
3.39k
    (!_functionType.isBareCall() ? 1 : 0);
2893
2894
3.39k
  evmasm::AssemblyItem endTag = m_context.newTag();
2895
2896
3.39k
  if (!returnSuccessConditionAndReturndata && !_tryCall)
2897
2.50k
  {
2898
    // Propagate error condition (if CALL pushes 0 on stack).
2899
2.50k
    m_context << Instruction::ISZERO;
2900
2.50k
    m_context.appendConditionalRevert(true);
2901
2.50k
  }
2902
889
  else
2903
889
    m_context << swapInstruction(remainsSize);
2904
3.39k
  utils().popStackSlots(remainsSize);
2905
2906
  // Only success flag is remaining on stack.
2907
2908
3.39k
  if (_tryCall)
2909
72
  {
2910
72
    m_context << Instruction::DUP1 << Instruction::ISZERO;
2911
72
    m_context.appendConditionalJumpTo(endTag);
2912
72
    m_context << Instruction::POP;
2913
72
  }
2914
2915
3.39k
  if (returnSuccessConditionAndReturndata)
2916
817
  {
2917
    // success condition is already there
2918
    // The return parameter types can be empty, when this function is used as
2919
    // an internal helper function e.g. for ``send`` and ``transfer``. In that
2920
    // case we're only interested in the success condition, not the return data.
2921
817
    if (!_functionType.returnParameterTypes().empty())
2922
755
      utils().returnDataToArray();
2923
817
  }
2924
2.58k
  else if (funKind == FunctionType::Kind::RIPEMD160)
2925
39
  {
2926
    // fix: built-in contract returns right-aligned data
2927
39
    utils().fetchFreeMemoryPointer();
2928
39
    utils().loadFromMemoryDynamic(IntegerType(160), false, true, false);
2929
39
    utils().convertType(IntegerType(160), FixedBytesType(20));
2930
39
  }
2931
2.54k
  else if (funKind == FunctionType::Kind::ECRecover)
2932
10
  {
2933
    // Output is 32 bytes before input / free mem pointer.
2934
    // Failing ecrecover cannot be detected, so we clear output before the call.
2935
10
    m_context << u256(32);
2936
10
    utils().fetchFreeMemoryPointer();
2937
10
    m_context << Instruction::SUB << Instruction::MLOAD;
2938
10
  }
2939
2.53k
  else if (!returnTypes.empty())
2940
2.27k
  {
2941
2.27k
    utils().fetchFreeMemoryPointer();
2942
    // Stack: return_data_start
2943
2944
    // The old decoder did not allocate any memory (i.e. did not touch the free
2945
    // memory pointer), but kept references to the return data for
2946
    // (statically-sized) arrays
2947
2.27k
    bool needToUpdateFreeMemoryPtr = false;
2948
2.27k
    if (dynamicReturnSize || m_context.useABICoderV2())
2949
2.26k
      needToUpdateFreeMemoryPtr = true;
2950
10
    else
2951
10
      for (auto const& retType: returnTypes)
2952
22
        if (dynamic_cast<ReferenceType const*>(retType))
2953
0
          needToUpdateFreeMemoryPtr = true;
2954
2955
    // Stack: return_data_start
2956
2.27k
    if (dynamicReturnSize)
2957
115
    {
2958
115
      solAssert(haveReturndatacopy, "");
2959
115
      m_context.appendInlineAssembly("{ returndatacopy(return_data_start, 0, returndatasize()) }", {"return_data_start"});
2960
115
    }
2961
2.15k
    else
2962
2.27k
      solAssert(retSize > 0, "");
2963
    // Always use the actual return length, and not our calculated expected length, if returndatacopy is supported.
2964
    // This ensures it can catch badly formatted input from external calls.
2965
2.27k
    m_context << (haveReturndatacopy ? evmasm::AssemblyItem(Instruction::RETURNDATASIZE) : u256(retSize));
2966
    // Stack: return_data_start return_data_size
2967
2.27k
    if (needToUpdateFreeMemoryPtr)
2968
2.26k
      m_context.appendInlineAssembly(R"({
2969
2.26k
        // round size to the next multiple of 32
2970
2.26k
        let newMem := add(start, and(add(size, 0x1f), not(0x1f)))
2971
2.26k
        mstore(0x40, newMem)
2972
2.26k
      })", {"start", "size"});
2973
2974
2.27k
    utils().abiDecode(returnTypes, true);
2975
2.27k
  }
2976
2977
3.39k
  if (_tryCall)
2978
72
  {
2979
    // Success branch will reach this, failure branch will directly jump to endTag.
2980
72
    m_context << u256(1);
2981
72
    m_context << endTag;
2982
72
  }
2983
3.39k
}
2984
2985
void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression)
2986
637
{
2987
637
  solUnimplementedAssert(_expectedType.isValueType(), "Not implemented for non-value types.");
2988
637
  acceptAndConvert(_expression, _expectedType, true);
2989
637
  utils().storeInMemoryDynamic(_expectedType);
2990
637
}
2991
2992
void ExpressionCompiler::appendVariable(VariableDeclaration const& _variable, Expression const& _expression)
2993
118k
{
2994
118k
  if (_variable.isConstant())
2995
3.14k
    acceptAndConvert(*_variable.value(), *_variable.annotation().type);
2996
115k
  else if (_variable.immutable())
2997
472
    setLValue<ImmutableItem>(_expression, _variable);
2998
115k
  else
2999
115k
    setLValueFromDeclaration(_variable, _expression);
3000
118k
}
3001
3002
void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression)
3003
115k
{
3004
115k
  if (m_context.isLocalVariable(&_declaration))
3005
87.4k
    setLValue<StackVariable>(_expression, dynamic_cast<VariableDeclaration const&>(_declaration));
3006
27.5k
  else if (m_context.isStateVariable(&_declaration))
3007
27.5k
  {
3008
27.5k
    if (dynamic_cast<VariableDeclaration const&>(_declaration).referenceLocation() == VariableDeclaration::Location::Transient)
3009
0
      setLValue<TransientStorageItem>(_expression, dynamic_cast<VariableDeclaration const&>(_declaration));
3010
27.5k
    else
3011
27.5k
      setLValue<StorageItem>(_expression, dynamic_cast<VariableDeclaration const&>(_declaration));
3012
27.5k
  }
3013
0
  else
3014
27.5k
    solAssert(false, "Identifier type not supported or identifier not found.");
3015
115k
}
3016
3017
void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression)
3018
83.0k
{
3019
83.0k
  setLValue<StorageItem>(_expression, *_expression.annotation().type);
3020
83.0k
}
3021
3022
bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token _op, Arithmetic _arithmetic)
3023
52.8k
{
3024
52.8k
  if (TokenTraits::isCompareOp(_op) || TokenTraits::isShiftOp(_op))
3025
45.0k
    return true;
3026
7.82k
  else if (
3027
7.82k
    _arithmetic == Arithmetic::Wrapping &&
3028
7.82k
    _type == Type::Category::Integer &&
3029
7.82k
    (_op == Token::Div || _op == Token::Mod || _op == Token::Exp)
3030
7.82k
  )
3031
    // We need cleanup for EXP because 0**0 == 1, but 0**0x100 == 0
3032
    // It would suffice to clean the exponent, though.
3033
40
    return true;
3034
7.78k
  else
3035
7.78k
    return false;
3036
52.8k
}
3037
3038
void ExpressionCompiler::acceptAndConvert(Expression const& _expression, Type const& _type, bool _cleanupNeeded)
3039
292k
{
3040
292k
  _expression.accept(*this);
3041
292k
  utils().convertType(*_expression.annotation().type, _type, _cleanupNeeded);
3042
292k
}
3043
3044
CompilerUtils ExpressionCompiler::utils()
3045
389k
{
3046
389k
  return CompilerUtils(m_context);
3047
389k
}