mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
User-defined literal suffixes: Code generation
This commit is contained in:
parent
3cbbfc890f
commit
9e708a98fd
@ -697,11 +697,48 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
// Callee removes them and pushes return values
|
// Callee removes them and pushes return values
|
||||||
|
|
||||||
evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
|
evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
|
||||||
|
|
||||||
|
if (!_functionCall.isSuffixCall())
|
||||||
|
{
|
||||||
for (unsigned i = 0; i < arguments.size(); ++i)
|
for (unsigned i = 0; i < arguments.size(); ++i)
|
||||||
acceptAndConvert(*arguments[i], *function.parameterTypes()[i]);
|
acceptAndConvert(*arguments[i], *parameterTypes[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solAssert(arguments.size() == 1);
|
||||||
|
solAssert(arguments[0]);
|
||||||
|
auto const* literal = dynamic_cast<Literal const*>(arguments[0].get());
|
||||||
|
Type const& literalType = *literal->annotation().type;
|
||||||
|
solAssert(literal);
|
||||||
|
solAssert(literal->annotation().type);
|
||||||
|
|
||||||
|
if (parameterTypes.size() == 1)
|
||||||
|
{
|
||||||
|
if (literalType.category() != Type::Category::StringLiteral)
|
||||||
|
// NOTE: For string literals we do not need to define the variable. The variable
|
||||||
|
// value will be embedded inside the conversion function.
|
||||||
|
m_context << literalType.literalValue(literal);
|
||||||
|
utils().convertType(literalType, *parameterTypes.at(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solAssert(parameterTypes.size() == 2);
|
||||||
|
|
||||||
|
auto const* rationalNumberType = dynamic_cast<RationalNumberType const*>(&literalType);
|
||||||
|
solAssert(rationalNumberType);
|
||||||
|
|
||||||
|
auto&& [mantissa, exponent] = rationalNumberType->fractionalDecomposition();
|
||||||
|
solAssert(mantissa && exponent);
|
||||||
|
m_context << mantissa->literalValue(nullptr);
|
||||||
|
utils().convertType(*mantissa, *parameterTypes.at(0));
|
||||||
|
m_context << exponent->literalValue(nullptr);
|
||||||
|
utils().convertType(*exponent, *parameterTypes.at(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_functionCall.expression().accept(*this);
|
_functionCall.expression().accept(*this);
|
||||||
|
|
||||||
unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes());
|
unsigned parameterSize = CompilerUtils::sizeOnStack(parameterTypes);
|
||||||
if (function.hasBoundFirstArgument())
|
if (function.hasBoundFirstArgument())
|
||||||
{
|
{
|
||||||
// stack: arg2, ..., argn, label, arg1
|
// stack: arg2, ..., argn, label, arg1
|
||||||
|
@ -997,16 +997,64 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
break;
|
break;
|
||||||
case FunctionType::Kind::Internal:
|
case FunctionType::Kind::Internal:
|
||||||
{
|
{
|
||||||
FunctionDefinition const* functionDef = ASTNode::resolveFunctionCall(_functionCall, &m_context.mostDerivedContract());
|
solAssert(functionType);
|
||||||
|
|
||||||
solAssert(!functionType->takesArbitraryParameters());
|
solAssert(!functionType->takesArbitraryParameters());
|
||||||
|
|
||||||
vector<string> args;
|
vector<string> args;
|
||||||
|
FunctionDefinition const* functionDef = nullptr;
|
||||||
|
|
||||||
|
if (!_functionCall.isSuffixCall())
|
||||||
|
{
|
||||||
|
functionDef = ASTNode::resolveFunctionCall(_functionCall, &m_context.mostDerivedContract());
|
||||||
|
|
||||||
if (functionType->hasBoundFirstArgument())
|
if (functionType->hasBoundFirstArgument())
|
||||||
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
|
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
|
||||||
|
|
||||||
for (size_t i = 0; i < arguments.size(); ++i)
|
for (size_t i = 0; i < arguments.size(); ++i)
|
||||||
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
|
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
functionDef = dynamic_cast<FunctionDefinition const*>(&functionType->declaration());
|
||||||
|
solAssert(functionDef);
|
||||||
|
solAssert(!functionDef->virtualSemantics());
|
||||||
|
solAssert(!functionType->hasBoundFirstArgument());
|
||||||
|
|
||||||
|
solAssert(arguments.size() == 1);
|
||||||
|
solAssert(arguments[0]);
|
||||||
|
auto const* literal = dynamic_cast<Literal const*>(arguments[0].get());
|
||||||
|
Type const& literalType = *literal->annotation().type;
|
||||||
|
solAssert(literal);
|
||||||
|
solAssert(literal->annotation().type);
|
||||||
|
|
||||||
|
if (parameterTypes.size() == 2)
|
||||||
|
{
|
||||||
|
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(&literalType);
|
||||||
|
solAssert(literalRationalType);
|
||||||
|
|
||||||
|
auto&& [mantissa, exponent] = literalRationalType->fractionalDecomposition();
|
||||||
|
solAssert(mantissa && exponent);
|
||||||
|
|
||||||
|
IRVariable mantissaVar(m_context.newYulVariable(), *mantissa);
|
||||||
|
define(mantissaVar) << toCompactHexWithPrefix(mantissa->literalValue(literal)) << "\n";
|
||||||
|
args += convert(mantissaVar, *parameterTypes[0]).stackSlots();
|
||||||
|
|
||||||
|
IRVariable exponentVar(m_context.newYulVariable(), *exponent);
|
||||||
|
define(exponentVar) << toCompactHexWithPrefix(exponent->literalValue(literal)) << "\n";
|
||||||
|
args += convert(exponentVar, *parameterTypes[1]).stackSlots();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solAssert(parameterTypes.size() == 1);
|
||||||
|
|
||||||
|
IRVariable value(m_context.newYulVariable(), literalType);
|
||||||
|
if (literalType.category() != Type::Category::StringLiteral)
|
||||||
|
// NOTE: For string literals we do not need to define the variable. The variable
|
||||||
|
// value will be embedded inside the conversion function.
|
||||||
|
define(value) << toCompactHexWithPrefix(literalType.literalValue(literal)) << "\n";
|
||||||
|
args += convert(value, *parameterTypes[0]).stackSlots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (functionDef)
|
if (functionDef)
|
||||||
{
|
{
|
||||||
@ -2500,10 +2548,14 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
|
|||||||
define(_literal) << toCompactHexWithPrefix(literalType.literalValue(&_literal)) << "\n";
|
define(_literal) << toCompactHexWithPrefix(literalType.literalValue(&_literal)) << "\n";
|
||||||
break;
|
break;
|
||||||
case Type::Category::StringLiteral:
|
case Type::Category::StringLiteral:
|
||||||
break; // will be done during conversion
|
// A string literal cannot be simply assigned to a Yul variable so we don't create one here.
|
||||||
|
// Instead any expression that uses it has to generate custom conversion code that
|
||||||
|
// depends on where the string ultimately ends up (storage, memory, ABI encoded data, etc.).
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
solUnimplemented("Only integer, boolean and string literals implemented for now.");
|
solUnimplemented("Only integer, boolean and string literals implemented for now.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user