mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add the ability to store variable types in wasm AST
This commit is contained in:
parent
840ff40263
commit
6a82d32ef6
@ -298,7 +298,8 @@ bytes BinaryTransform::run(Module const& _module)
|
|||||||
|
|
||||||
bytes BinaryTransform::operator()(Literal const& _literal)
|
bytes BinaryTransform::operator()(Literal const& _literal)
|
||||||
{
|
{
|
||||||
return toBytes(Opcode::I64Const) + lebEncodeSigned(_literal.value);
|
yulAssert(holds_alternative<uint64_t>(_literal.value), "");
|
||||||
|
return toBytes(Opcode::I64Const) + lebEncodeSigned(get<uint64_t>(_literal.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes BinaryTransform::operator()(StringLiteral const&)
|
bytes BinaryTransform::operator()(StringLiteral const&)
|
||||||
@ -457,8 +458,8 @@ bytes BinaryTransform::operator()(FunctionDefinition const& _function)
|
|||||||
|
|
||||||
m_locals.clear();
|
m_locals.clear();
|
||||||
size_t varIdx = 0;
|
size_t varIdx = 0;
|
||||||
for (size_t i = 0; i < _function.parameterNames.size(); ++i)
|
for (size_t i = 0; i < _function.parameters.size(); ++i)
|
||||||
m_locals[_function.parameterNames[i]] = varIdx++;
|
m_locals[_function.parameters[i].name] = varIdx++;
|
||||||
for (size_t i = 0; i < _function.locals.size(); ++i)
|
for (size_t i = 0; i < _function.locals.size(); ++i)
|
||||||
m_locals[_function.locals[i].variableName] = varIdx++;
|
m_locals[_function.locals[i].variableName] = varIdx++;
|
||||||
|
|
||||||
@ -484,8 +485,8 @@ BinaryTransform::Type BinaryTransform::typeOf(FunctionDefinition const& _funDef)
|
|||||||
{
|
{
|
||||||
|
|
||||||
return {
|
return {
|
||||||
encodeTypes(vector<wasm::Type>(_funDef.parameterNames.size(), wasm::Type::i64)),
|
encodeTypes(vector<wasm::Type>(_funDef.parameters.size(), wasm::Type::i64)),
|
||||||
encodeTypes(vector<wasm::Type>(_funDef.returns ? 1 : 0, wasm::Type::i64))
|
encodeTypes(vector<wasm::Type>(_funDef.returnType.has_value() ? 1 : 0, wasm::Type::i64))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,8 @@ string TextTransform::run(wasm::Module const& _module)
|
|||||||
|
|
||||||
string TextTransform::operator()(wasm::Literal const& _literal)
|
string TextTransform::operator()(wasm::Literal const& _literal)
|
||||||
{
|
{
|
||||||
return "(i64.const " + to_string(_literal.value) + ")";
|
yulAssert(holds_alternative<uint64_t>(_literal.value), "");
|
||||||
|
return "(i64.const " + to_string(get<uint64_t>(_literal.value)) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
string TextTransform::operator()(wasm::StringLiteral const& _literal)
|
string TextTransform::operator()(wasm::StringLiteral const& _literal)
|
||||||
@ -164,9 +165,9 @@ string TextTransform::indented(string const& _in)
|
|||||||
string TextTransform::transform(wasm::FunctionDefinition const& _function)
|
string TextTransform::transform(wasm::FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
string ret = "(func $" + _function.name + "\n";
|
string ret = "(func $" + _function.name + "\n";
|
||||||
for (auto const& param: _function.parameterNames)
|
for (auto const& param: _function.parameters)
|
||||||
ret += " (param $" + param + " i64)\n";
|
ret += " (param $" + param.name + " i64)\n";
|
||||||
if (_function.returns)
|
if (_function.returnType.has_value())
|
||||||
ret += " (result i64)\n";
|
ret += " (result i64)\n";
|
||||||
for (auto const& local: _function.locals)
|
for (auto const& local: _function.locals)
|
||||||
ret += " (local $" + local.variableName + " i64)\n";
|
ret += " (local $" + local.variableName + " i64)\n";
|
||||||
|
@ -36,6 +36,9 @@ enum class Type
|
|||||||
i64,
|
i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TypedName { std::string name; Type type; };
|
||||||
|
using TypedNameList = std::vector<TypedName>;
|
||||||
|
|
||||||
struct Literal;
|
struct Literal;
|
||||||
struct StringLiteral;
|
struct StringLiteral;
|
||||||
struct LocalVariable;
|
struct LocalVariable;
|
||||||
@ -56,7 +59,7 @@ using Expression = std::variant<
|
|||||||
Block, If, Loop, Branch, BranchIf, Return
|
Block, If, Loop, Branch, BranchIf, Return
|
||||||
>;
|
>;
|
||||||
|
|
||||||
struct Literal { uint64_t value; };
|
struct Literal { std::variant<uint32_t, uint64_t> value; };
|
||||||
struct StringLiteral { std::string value; };
|
struct StringLiteral { std::string value; };
|
||||||
struct LocalVariable { std::string name; };
|
struct LocalVariable { std::string name; };
|
||||||
struct GlobalVariable { std::string name; };
|
struct GlobalVariable { std::string name; };
|
||||||
@ -76,8 +79,8 @@ struct Branch { Label label; };
|
|||||||
struct Return {};
|
struct Return {};
|
||||||
struct BranchIf { Label label; std::unique_ptr<Expression> condition; };
|
struct BranchIf { Label label; std::unique_ptr<Expression> condition; };
|
||||||
|
|
||||||
struct VariableDeclaration { std::string variableName; };
|
struct VariableDeclaration { std::string variableName; Type type; };
|
||||||
struct GlobalVariableDeclaration { std::string variableName; };
|
struct GlobalVariableDeclaration { std::string variableName; Type type; };
|
||||||
struct FunctionImport {
|
struct FunctionImport {
|
||||||
std::string module;
|
std::string module;
|
||||||
std::string externalName;
|
std::string externalName;
|
||||||
@ -89,8 +92,8 @@ struct FunctionImport {
|
|||||||
struct FunctionDefinition
|
struct FunctionDefinition
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> parameterNames;
|
std::vector<TypedName> parameters;
|
||||||
bool returns;
|
std::optional<Type> returnType;
|
||||||
std::vector<VariableDeclaration> locals;
|
std::vector<VariableDeclaration> locals;
|
||||||
std::vector<Expression> body;
|
std::vector<Expression> body;
|
||||||
};
|
};
|
||||||
|
@ -88,7 +88,7 @@ wasm::Expression WasmCodeTransform::operator()(VariableDeclaration const& _varDe
|
|||||||
for (auto const& var: _varDecl.variables)
|
for (auto const& var: _varDecl.variables)
|
||||||
{
|
{
|
||||||
variableNames.emplace_back(var.name.str());
|
variableNames.emplace_back(var.name.str());
|
||||||
m_localVariables.emplace_back(wasm::VariableDeclaration{variableNames.back()});
|
m_localVariables.emplace_back(wasm::VariableDeclaration{variableNames.back(), wasm::Type::i64});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_varDecl.value)
|
if (_varDecl.value)
|
||||||
@ -184,7 +184,7 @@ wasm::Expression WasmCodeTransform::operator()(Literal const& _literal)
|
|||||||
{
|
{
|
||||||
u256 value = valueOfLiteral(_literal);
|
u256 value = valueOfLiteral(_literal);
|
||||||
yulAssert(value <= numeric_limits<uint64_t>::max(), "Literal too large: " + value.str());
|
yulAssert(value <= numeric_limits<uint64_t>::max(), "Literal too large: " + value.str());
|
||||||
return wasm::Literal{uint64_t(value)};
|
return wasm::Literal{static_cast<uint64_t>(value)};
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm::Expression WasmCodeTransform::operator()(If const& _if)
|
wasm::Expression WasmCodeTransform::operator()(If const& _if)
|
||||||
@ -193,7 +193,7 @@ wasm::Expression WasmCodeTransform::operator()(If const& _if)
|
|||||||
|
|
||||||
vector<wasm::Expression> args;
|
vector<wasm::Expression> args;
|
||||||
args.emplace_back(visitReturnByValue(*_if.condition));
|
args.emplace_back(visitReturnByValue(*_if.condition));
|
||||||
args.emplace_back(wasm::Literal{0});
|
args.emplace_back(wasm::Literal{static_cast<uint64_t>(0)});
|
||||||
return wasm::If{
|
return wasm::If{
|
||||||
make_unique<wasm::Expression>(wasm::BuiltinCall{"i64.ne", std::move(args)}),
|
make_unique<wasm::Expression>(wasm::BuiltinCall{"i64.ne", std::move(args)}),
|
||||||
visit(_if.body.statements),
|
visit(_if.body.statements),
|
||||||
@ -205,7 +205,7 @@ wasm::Expression WasmCodeTransform::operator()(Switch const& _switch)
|
|||||||
{
|
{
|
||||||
wasm::Block block;
|
wasm::Block block;
|
||||||
string condition = m_nameDispenser.newName("condition"_yulstring).str();
|
string condition = m_nameDispenser.newName("condition"_yulstring).str();
|
||||||
m_localVariables.emplace_back(wasm::VariableDeclaration{condition});
|
m_localVariables.emplace_back(wasm::VariableDeclaration{condition, wasm::Type::i64});
|
||||||
block.statements.emplace_back(wasm::LocalAssignment{condition, visit(*_switch.expression)});
|
block.statements.emplace_back(wasm::LocalAssignment{condition, visit(*_switch.expression)});
|
||||||
|
|
||||||
vector<wasm::Expression>* currentBlock = &block.statements;
|
vector<wasm::Expression>* currentBlock = &block.statements;
|
||||||
@ -325,10 +325,11 @@ wasm::FunctionDefinition WasmCodeTransform::translateFunction(yul::FunctionDefin
|
|||||||
wasm::FunctionDefinition fun;
|
wasm::FunctionDefinition fun;
|
||||||
fun.name = _fun.name.str();
|
fun.name = _fun.name.str();
|
||||||
for (auto const& param: _fun.parameters)
|
for (auto const& param: _fun.parameters)
|
||||||
fun.parameterNames.emplace_back(param.name.str());
|
fun.parameters.push_back({param.name.str(), wasm::Type::i64});
|
||||||
for (auto const& retParam: _fun.returnVariables)
|
for (auto const& retParam: _fun.returnVariables)
|
||||||
fun.locals.emplace_back(wasm::VariableDeclaration{retParam.name.str()});
|
fun.locals.emplace_back(wasm::VariableDeclaration{retParam.name.str(), wasm::Type::i64});
|
||||||
fun.returns = !_fun.returnVariables.empty();
|
if (!_fun.returnVariables.empty())
|
||||||
|
fun.returnType = wasm::Type::i64;
|
||||||
|
|
||||||
yulAssert(m_localVariables.empty(), "");
|
yulAssert(m_localVariables.empty(), "");
|
||||||
yulAssert(m_functionBodyLabel.empty(), "");
|
yulAssert(m_functionBodyLabel.empty(), "");
|
||||||
@ -400,7 +401,8 @@ void WasmCodeTransform::allocateGlobals(size_t _amount)
|
|||||||
{
|
{
|
||||||
while (m_globalVariables.size() < _amount)
|
while (m_globalVariables.size() < _amount)
|
||||||
m_globalVariables.emplace_back(wasm::GlobalVariableDeclaration{
|
m_globalVariables.emplace_back(wasm::GlobalVariableDeclaration{
|
||||||
m_nameDispenser.newName("global_"_yulstring).str()
|
m_nameDispenser.newName("global_"_yulstring).str(),
|
||||||
|
wasm::Type::i64
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user