User-defined literal suffixes: Code generation

This commit is contained in:
chriseth 2022-02-10 19:16:10 +01:00 committed by Kamil Śliwak
parent 0ad290ad06
commit fdda7d6bd1
2 changed files with 65 additions and 10 deletions

View File

@ -697,11 +697,34 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// Callee removes them and pushes return values
evmasm::AssemblyItem returnLabel = m_context.pushNewTag();
for (unsigned i = 0; i < arguments.size(); ++i)
acceptAndConvert(*arguments[i], *function.parameterTypes()[i]);
if (_functionCall.isSuffixCall() && parameterTypes.size() != 1)
{
solAssert(parameterTypes.size() == 2);
solAssert(arguments.size() == 1 && arguments[0]);
auto const* literal = dynamic_cast<Literal const*>(arguments[0].get());
solAssert(literal);
solAssert(literal->annotation().type);
auto const* rationalNumberType = dynamic_cast<RationalNumberType const*>(literal->annotation().type);
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));
}
else
{
for (unsigned i = 0; i < arguments.size(); ++i)
acceptAndConvert(*arguments[i], *parameterTypes[i]);
}
_functionCall.expression().accept(*this);
unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes());
unsigned parameterSize = CompilerUtils::sizeOnStack(parameterTypes);
if (function.hasBoundFirstArgument())
{
// stack: arg2, ..., argn, label, arg1

View File

@ -997,16 +997,44 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
break;
case FunctionType::Kind::Internal:
{
FunctionDefinition const* functionDef = ASTNode::resolveFunctionCall(_functionCall, &m_context.mostDerivedContract());
solAssert(functionType);
solAssert(!functionType->takesArbitraryParameters());
vector<string> args;
if (functionType->hasBoundFirstArgument())
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
FunctionDefinition const* functionDef = nullptr;
for (size_t i = 0; i < arguments.size(); ++i)
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
if (_functionCall.isSuffixCall() && parameterTypes.size() != 1)
{
functionDef = dynamic_cast<FunctionDefinition const*>(&functionType->declaration());
solAssert(functionDef);
solAssert(!functionDef->virtualSemantics());
solAssert(!functionType->hasBoundFirstArgument());
solAssert(parameterTypes.size() == 2);
solAssert(arguments.size() == 1 && arguments[0]);
auto const* literal = dynamic_cast<Literal const*>(arguments[0].get());
solAssert(literal);
solAssert(literal->annotation().type);
auto const* literalRationalType = dynamic_cast<RationalNumberType const*>(literal->annotation().type);
solAssert(literalRationalType);
auto&& [mantissa, exponent] = literalRationalType->fractionalDecomposition();
solAssert(mantissa && exponent);
args.emplace_back(toCompactHexWithPrefix(mantissa->literalValue(literal)));
args.emplace_back(toCompactHexWithPrefix(exponent->literalValue(literal)));
}
else
{
functionDef = ASTNode::resolveFunctionCall(_functionCall, &m_context.mostDerivedContract());
if (functionType->hasBoundFirstArgument())
args += IRVariable(_functionCall.expression()).part("self").stackSlots();
for (size_t i = 0; i < arguments.size(); ++i)
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
}
if (functionDef)
{
@ -2500,10 +2528,14 @@ bool IRGeneratorForStatements::visit(Literal const& _literal)
define(_literal) << toCompactHexWithPrefix(literalType.literalValue(&_literal)) << "\n";
break;
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:
solUnimplemented("Only integer, boolean and string literals implemented for now.");
}
return false;
}