Skip to content

Commit f6a57af

Browse files
axicekpyron
andcommitted
Add LiteralKind to Dialect.literalArguments
Co-authored-by: Daniel Kirchner <daniel@ekpyron.org>
1 parent b8fd409 commit f6a57af

10 files changed

+47
-51
lines changed

libyul/AsmAnalysis.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,14 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
272272
auto watcher = m_errorReporter.errorWatcher();
273273
vector<YulString> const* parameterTypes = nullptr;
274274
vector<YulString> const* returnTypes = nullptr;
275-
vector<bool> const* needsLiteralArguments = nullptr;
275+
vector<optional<LiteralKind>> const* literalArguments = nullptr;
276276

277277
if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name))
278278
{
279279
parameterTypes = &f->parameters;
280280
returnTypes = &f->returns;
281-
if (f->literalArguments)
282-
needsLiteralArguments = &f->literalArguments.value();
281+
if (!f->literalArguments.empty())
282+
literalArguments = &f->literalArguments;
283283

284284
validateInstructions(_funCall);
285285
}
@@ -318,7 +318,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
318318
for (size_t i = _funCall.arguments.size(); i > 0; i--)
319319
{
320320
Expression const& arg = _funCall.arguments[i - 1];
321-
bool isLiteralArgument = needsLiteralArguments && (*needsLiteralArguments)[i - 1];
321+
bool isLiteralArgument = literalArguments && (*literalArguments)[i - 1].has_value();
322322
bool isStringLiteral = holds_alternative<Literal>(arg) && get<Literal>(arg).kind == LiteralKind::String;
323323

324324
if (isLiteralArgument && isStringLiteral)

libyul/Dialect.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,13 @@ struct BuiltinFunction
4848
ControlFlowSideEffects controlFlowSideEffects;
4949
/// If true, this is the msize instruction.
5050
bool isMSize = false;
51-
/// If set, same length as the arguments, if true at index i, the i'th argument has to be a literal which means it can't be moved to variables.
52-
std::optional<std::vector<bool>> literalArguments;
51+
/// Must be empty or the same length as the arguments.
52+
/// If set at index i, the i'th argument has to be a literal which means it can't be moved to variables.
53+
std::vector<std::optional<LiteralKind>> literalArguments{};
54+
std::optional<LiteralKind> literalArgument(size_t i) const
55+
{
56+
return literalArguments.empty() ? std::nullopt : literalArguments.at(i);
57+
}
5358
};
5459

5560
struct Dialect: boost::noncopyable

libyul/backends/evm/EVMDialect.cpp

+8-11
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
7070
f.controlFlowSideEffects.terminates = evmasm::SemanticInformation::terminatesControlFlow(_instruction);
7171
f.controlFlowSideEffects.reverts = evmasm::SemanticInformation::reverts(_instruction);
7272
f.isMSize = _instruction == evmasm::Instruction::MSIZE;
73-
f.literalArguments.reset();
73+
f.literalArguments.clear();
7474
f.instruction = _instruction;
7575
f.generateCode = [_instruction](
7676
FunctionCall const& _call,
@@ -90,7 +90,7 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
9090
size_t _params,
9191
size_t _returns,
9292
SideEffects _sideEffects,
93-
vector<bool> _literalArguments,
93+
vector<optional<LiteralKind>> _literalArguments,
9494
std::function<void(FunctionCall const&, AbstractAssembly&, BuiltinContext&, std::function<void(Expression const&)>)> _generateCode
9595
)
9696
{
@@ -102,10 +102,7 @@ pair<YulString, BuiltinFunctionForEVM> createFunction(
102102
f.parameters.resize(_params);
103103
f.returns.resize(_returns);
104104
f.sideEffects = std::move(_sideEffects);
105-
if (!_literalArguments.empty())
106-
f.literalArguments = std::move(_literalArguments);
107-
else
108-
f.literalArguments.reset();
105+
f.literalArguments = std::move(_literalArguments);
109106
f.isMSize = false;
110107
f.instruction = {};
111108
f.generateCode = std::move(_generateCode);
@@ -135,7 +132,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
135132

136133
if (_objectAccess)
137134
{
138-
builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {true}, [](
135+
builtins.emplace(createFunction("linkersymbol", 1, 1, SideEffects{}, {LiteralKind::String}, [](
139136
FunctionCall const& _call,
140137
AbstractAssembly& _assembly,
141138
BuiltinContext&,
@@ -145,7 +142,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
145142
Expression const& arg = _call.arguments.front();
146143
_assembly.appendLinkerSymbol(std::get<Literal>(arg).value.str());
147144
}));
148-
builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {true}, [](
145+
builtins.emplace(createFunction("datasize", 1, 1, SideEffects{}, {LiteralKind::String}, [](
149146
FunctionCall const& _call,
150147
AbstractAssembly& _assembly,
151148
BuiltinContext& _context,
@@ -167,7 +164,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
167164
_assembly.appendDataSize(subIdPath);
168165
}
169166
}));
170-
builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {true}, [](
167+
builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {LiteralKind::String}, [](
171168
FunctionCall const& _call,
172169
AbstractAssembly& _assembly,
173170
BuiltinContext& _context,
@@ -210,7 +207,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
210207
2,
211208
0,
212209
SideEffects{false, false, false, false, true},
213-
{true, false},
210+
{LiteralKind::String, std::nullopt},
214211
[](
215212
FunctionCall const& _call,
216213
AbstractAssembly& _assembly,
@@ -230,7 +227,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
230227
1,
231228
1,
232229
SideEffects{},
233-
{true},
230+
{LiteralKind::String},
234231
[](
235232
FunctionCall const& _call,
236233
AbstractAssembly& _assembly,

libyul/backends/evm/NoOutputAssembly.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ NoOutputEVMDialect::NoOutputEVMDialect(EVMDialect const& _copyFrom):
170170
for (size_t j = 0; j < _call.arguments.size(); j++)
171171
{
172172
size_t const i = _call.arguments.size() - j - 1;
173-
if (!(fun.second.literalArguments && (*fun.second.literalArguments)[i]))
173+
if (!fun.second.literalArgument(i))
174174
{
175175
_visitExpression(_call.arguments[i]);
176176
visited++;

libyul/backends/wasm/WasmCodeTransform.cpp

+9-11
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,20 @@ wasm::Expression WasmCodeTransform::operator()(FunctionCall const& _call)
140140
m_functionsToImport[builtin->name] = std::move(imp);
141141
}
142142
}
143-
else if (builtin->literalArguments && contains(builtin->literalArguments.value(), true))
143+
else
144144
{
145-
vector<wasm::Expression> literals;
145+
vector<wasm::Expression> arguments;
146146
for (size_t i = 0; i < _call.arguments.size(); i++)
147-
if (builtin->literalArguments.value()[i])
148-
literals.emplace_back(wasm::StringLiteral{std::get<Literal>(_call.arguments[i]).value.str()});
147+
if (builtin->literalArgument(i))
148+
{
149+
yulAssert(builtin->literalArgument(i) == LiteralKind::String, "");
150+
arguments.emplace_back(wasm::StringLiteral{std::get<Literal>(_call.arguments[i]).value.str()});
151+
}
149152
else
150-
literals.emplace_back(visitReturnByValue(_call.arguments[i]));
153+
arguments.emplace_back(visitReturnByValue(_call.arguments[i]));
151154

152-
return wasm::BuiltinCall{_call.functionName.name.str(), std::move(literals)};
155+
return wasm::BuiltinCall{_call.functionName.name.str(), std::move(arguments)};
153156
}
154-
else
155-
return wasm::BuiltinCall{
156-
_call.functionName.name.str(),
157-
visit(_call.arguments)
158-
};
159157
}
160158

161159
// If this function returns multiple values, then the first one will

libyul/backends/wasm/WasmDialect.cpp

+6-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <libyul/backends/wasm/WasmDialect.h>
2323

24+
#include <libyul/AsmData.h>
2425
#include <libyul/Exceptions.h>
2526

2627
using namespace std;
@@ -119,8 +120,8 @@ WasmDialect::WasmDialect()
119120
m_functions["unreachable"_yulstring].controlFlowSideEffects.terminates = true;
120121
m_functions["unreachable"_yulstring].controlFlowSideEffects.reverts = true;
121122

122-
addFunction("datasize", {i64}, {i64}, true, {true});
123-
addFunction("dataoffset", {i64}, {i64}, true, {true});
123+
addFunction("datasize", {i64}, {i64}, true, {LiteralKind::String});
124+
addFunction("dataoffset", {i64}, {i64}, true, {LiteralKind::String});
124125

125126
addEthereumExternals();
126127
}
@@ -221,7 +222,7 @@ void WasmDialect::addEthereumExternals()
221222
f.controlFlowSideEffects = ext.controlFlowSideEffects;
222223
f.isMSize = false;
223224
f.sideEffects.invalidatesStorage = (ext.name == "storageStore");
224-
f.literalArguments.reset();
225+
f.literalArguments.clear();
225226
}
226227
}
227228

@@ -230,7 +231,7 @@ void WasmDialect::addFunction(
230231
vector<YulString> _params,
231232
vector<YulString> _returns,
232233
bool _movable,
233-
std::vector<bool> _literalArguments
234+
vector<optional<LiteralKind>> _literalArguments
234235
)
235236
{
236237
YulString name{move(_name)};
@@ -241,8 +242,5 @@ void WasmDialect::addFunction(
241242
f.returns = std::move(_returns);
242243
f.sideEffects = _movable ? SideEffects{} : SideEffects::worst();
243244
f.isMSize = false;
244-
if (!_literalArguments.empty())
245-
f.literalArguments = std::move(_literalArguments);
246-
else
247-
f.literalArguments.reset();
245+
f.literalArguments = std::move(_literalArguments);
248246
}

libyul/backends/wasm/WasmDialect.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct WasmDialect: public Dialect
6262
std::vector<YulString> _params,
6363
std::vector<YulString> _returns,
6464
bool _movable = true,
65-
std::vector<bool> _literalArguments = std::vector<bool>{}
65+
std::vector<std::optional<LiteralKind>> _literalArguments = std::vector<std::optional<LiteralKind>>{}
6666
);
6767

6868
std::map<YulString, BuiltinFunction> m_functions;

libyul/backends/wasm/WordSizeTransform.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ void WordSizeTransform::operator()(FunctionDefinition& _fd)
4242

4343
void WordSizeTransform::operator()(FunctionCall& _fc)
4444
{
45-
vector<bool> const* literalArguments = nullptr;
45+
vector<optional<LiteralKind>> const* literalArguments = nullptr;
4646

4747
if (BuiltinFunction const* fun = m_inputDialect.builtin(_fc.functionName.name))
48-
if (fun->literalArguments)
49-
literalArguments = &fun->literalArguments.value();
48+
if (!fun->literalArguments.empty())
49+
literalArguments = &fun->literalArguments;
5050

5151
vector<Expression> newArgs;
5252

5353
for (size_t i = 0; i < _fc.arguments.size(); i++)
54-
if (!literalArguments || !(*literalArguments)[i])
54+
if (!literalArguments || !(*literalArguments)[i].has_value())
5555
newArgs += expandValueToVector(_fc.arguments[i]);
5656
else
5757
{
@@ -109,7 +109,8 @@ void WordSizeTransform::operator()(Block& _block)
109109
if (BuiltinFunction const* f = m_inputDialect.builtin(std::get<FunctionCall>(*varDecl.value).functionName.name))
110110
if (f->name == "datasize"_yulstring || f->name == "dataoffset"_yulstring)
111111
{
112-
yulAssert(f->literalArguments && f->literalArguments.value()[0], "");
112+
yulAssert(f->literalArguments.size() == 1, "");
113+
yulAssert(f->literalArguments.at(0) == LiteralKind::String, "");
113114
yulAssert(varDecl.variables.size() == 1, "");
114115
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
115116
vector<Statement> ret;
@@ -169,7 +170,8 @@ void WordSizeTransform::operator()(Block& _block)
169170
if (BuiltinFunction const* f = m_inputDialect.builtin(std::get<FunctionCall>(*assignment.value).functionName.name))
170171
if (f->name == "datasize"_yulstring || f->name == "dataoffset"_yulstring)
171172
{
172-
yulAssert(f->literalArguments && f->literalArguments.value()[0], "");
173+
yulAssert(f->literalArguments.size() == 1, "");
174+
yulAssert(f->literalArguments[0] == LiteralKind::String, "");
173175
yulAssert(assignment.variableNames.size() == 1, "");
174176
auto newLhs = generateU64IdentifierNames(assignment.variableNames[0].name);
175177
vector<Statement> ret;

libyul/optimiser/CommonSubexpressionEliminator.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e)
6767
// We should not modify function arguments that have to be literals
6868
// Note that replacing the function call entirely is fine,
6969
// if the function call is movable.
70-
if (!builtin->literalArguments || !builtin->literalArguments.value()[i - 1])
70+
if (!builtin->literalArgument(i - 1))
7171
visit(funCall.arguments[i - 1]);
7272

7373
descend = false;

libyul/optimiser/ExpressionSplitter.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,10 @@ void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast)
4646

4747
void ExpressionSplitter::operator()(FunctionCall& _funCall)
4848
{
49-
vector<bool> const* literalArgs = nullptr;
50-
51-
if (BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name))
52-
if (builtin->literalArguments)
53-
literalArgs = &builtin->literalArguments.value();
49+
BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name);
5450

5551
for (size_t i = _funCall.arguments.size(); i > 0; i--)
56-
if (!literalArgs || !(*literalArgs)[i - 1])
52+
if (!builtin || !builtin->literalArgument(i - 1))
5753
outlineExpression(_funCall.arguments[i - 1]);
5854
}
5955

0 commit comments

Comments
 (0)