Coverage Report

Created: 2022-08-24 06:55

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