Coverage Report

Created: 2026-06-30 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/libsolidity/experimental/codegen/IRGenerator.cpp
Line
Count
Source
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
#include <libsolidity/experimental/codegen/IRGenerator.h>
20
#include <libsolidity/experimental/codegen/IRGenerationContext.h>
21
#include <libsolidity/experimental/codegen/IRGeneratorForStatements.h>
22
23
#include <libsolidity/experimental/codegen/Common.h>
24
25
#include <libsolidity/experimental/analysis/Analysis.h>
26
#include <libsolidity/experimental/analysis/TypeInference.h>
27
28
#include <libsolidity/experimental/ast/TypeSystemHelper.h>
29
30
#include <libyul/AsmPrinter.h>
31
#include <libyul/AST.h>
32
#include <libyul/optimiser/ASTCopier.h>
33
34
#include <liblangutil/SourceReferenceFormatter.h>
35
36
#include <libsolutil/Whiskers.h>
37
38
#include <range/v3/view/drop_last.hpp>
39
40
#include <variant>
41
42
using namespace solidity;
43
using namespace solidity::frontend::experimental;
44
using namespace solidity::langutil;
45
using namespace solidity::util;
46
47
IRGenerator::IRGenerator(
48
  EVMVersion _evmVersion,
49
  frontend::RevertStrings, std::map<std::string, unsigned int>,
50
  DebugInfoSelection const&,
51
  CharStreamProvider const*,
52
  Analysis const& _analysis
53
):
54
0
  m_evmVersion(_evmVersion),
55
  //m_debugInfoSelection(_debugInfoSelection),
56
  //m_soliditySourceProvider(_soliditySourceProvider),
57
0
  m_env(_analysis.typeSystem().env().clone()),
58
0
  m_context{_analysis, &m_env, {}, {}}
59
0
{
60
0
}
61
62
std::string IRGenerator::run(
63
  ContractDefinition const& _contract,
64
  bytes const& /*_cborMetadata*/,
65
  std::map<ContractDefinition const*, std::string_view const> const& /*_otherYulSources*/
66
)
67
0
{
68
0
  Whiskers t(R"(
69
0
    object "<CreationObject>" {
70
0
      code {
71
0
        codecopy(0, dataoffset("<DeployedObject>"), datasize("<DeployedObject>"))
72
0
        return(0, datasize("<DeployedObject>"))
73
0
      }
74
0
      object "<DeployedObject>" {
75
0
        code {
76
0
          <code>
77
0
        }
78
0
      }
79
0
    }
80
0
  )");
81
0
  t("CreationObject", IRNames::creationObject(_contract));
82
0
  t("DeployedObject", IRNames::deployedObject(_contract));
83
0
  t("code", generate(_contract));
84
85
0
  return t.render();
86
0
}
87
88
std::string IRGenerator::generate(ContractDefinition const& _contract)
89
0
{
90
0
  std::stringstream code;
91
0
  code << "{\n";
92
0
  if (_contract.fallbackFunction())
93
0
  {
94
0
    auto type = m_context.analysis.annotation<TypeInference>(*_contract.fallbackFunction()).type;
95
0
    solAssert(type);
96
0
    type = m_context.env->resolve(*type);
97
0
    code << IRNames::function(*m_context.env, *_contract.fallbackFunction(), *type) << "()\n";
98
0
    m_context.enqueueFunctionDefinition(_contract.fallbackFunction(), *type);
99
0
  }
100
0
  code << "revert(0,0)\n";
101
0
  code << "}\n";
102
103
0
  while (!m_context.functionQueue.empty())
104
0
  {
105
0
    auto queueEntry = m_context.functionQueue.front();
106
0
    m_context.functionQueue.pop_front();
107
0
    auto& generatedTypes = m_context.generatedFunctions.insert(std::make_pair(queueEntry.function, std::vector<Type>{})).first->second;
108
0
    if (!util::contains_if(generatedTypes, [&](auto const& _generatedType) { return m_context.env->typeEquals(_generatedType, queueEntry.type); }))
109
0
    {
110
0
      generatedTypes.emplace_back(queueEntry.type);
111
0
      code << generate(*queueEntry.function, queueEntry.type);
112
0
    }
113
0
  }
114
115
0
  return code.str();
116
0
}
117
118
std::string IRGenerator::generate(FunctionDefinition const& _function, Type _type)
119
0
{
120
0
  TypeEnvironment newEnv = m_context.env->clone();
121
0
  ScopedSaveAndRestore envRestore{m_context.env, &newEnv};
122
0
  auto type = m_context.analysis.annotation<TypeInference>(_function).type;
123
0
  solAssert(type);
124
0
  for (auto err: newEnv.unify(*type, _type))
125
0
  {
126
0
    TypeEnvironmentHelpers helper{newEnv};
127
0
    solAssert(false, helper.typeToString(*type) + " <-> " + helper.typeToString(_type));
128
0
  }
129
0
  std::stringstream code;
130
0
  code << "function " << IRNames::function(newEnv, _function, _type) << "(";
131
0
  if (_function.parameters().size() > 1)
132
0
    for (auto const& arg: _function.parameters() | ranges::views::drop_last(1))
133
0
      code << IRNames::localVariable(*arg) << ", ";
134
0
  if (!_function.parameters().empty())
135
0
    code << IRNames::localVariable(*_function.parameters().back());
136
0
  code << ")";
137
0
  if (_function.experimentalReturnExpression())
138
0
  {
139
0
    auto returnType = m_context.analysis.annotation<TypeInference>(*_function.experimentalReturnExpression()).type;
140
0
    solAssert(returnType);
141
0
    if (!m_env.typeEquals(*returnType, m_context.analysis.typeSystem().type(PrimitiveType::Unit, {})))
142
0
    {
143
      // TODO: destructure tuples.
144
0
      code << " -> " << IRNames::localVariable(*_function.experimentalReturnExpression()) << " ";
145
0
    }
146
0
  }
147
0
  code << "{\n";
148
0
  for (auto _statement: _function.body().statements())
149
0
  {
150
0
    IRGeneratorForStatements statementGenerator{m_context};
151
0
    code << statementGenerator.generate(*_statement);
152
0
  }
153
0
  code << "}\n";
154
0
  return code.str();
155
0
}