From fdda7d6bd1a381ff67dda6832a627e71383bee1e Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Feb 2022 19:16:10 +0100 Subject: [PATCH] User-defined literal suffixes: Code generation --- libsolidity/codegen/ExpressionCompiler.cpp | 29 ++++++++++-- .../codegen/ir/IRGeneratorForStatements.cpp | 46 ++++++++++++++++--- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 25bd15d5a..aee7643a1 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -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(arguments[0].get()); + solAssert(literal); + solAssert(literal->annotation().type); + + auto const* rationalNumberType = dynamic_cast(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 diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 509cc28c7..8aa1d1375 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -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 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(&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(arguments[0].get()); + solAssert(literal); + solAssert(literal->annotation().type); + + auto const* literalRationalType = dynamic_cast(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; }