Support constant numbers in inline assembly.

This commit is contained in:
chriseth
2019-07-02 14:01:05 +02:00
parent b8dbf7d2a8
commit cdd137e3d1
11 changed files with 122 additions and 10 deletions
+17 -4
View File
@@ -629,14 +629,27 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
{
solAssert(var->type(), "Expected variable type!");
if (var->isConstant())
if (var->isConstant() && (!type(*var)->isValueType() || (
type(*var->value())->category() != Type::Category::RationalNumber &&
dynamic_cast<Literal const*>(var->value().get()) == nullptr
)))
{
m_errorReporter.typeError(_identifier.location, "Constant variables not supported by inline assembly.");
m_errorReporter.typeError(_identifier.location, "Only direct number constants are supported by inline assembly.");
return size_t(-1);
}
else if (var->isConstant() && _context == yul::IdentifierContext::LValue)
{
m_errorReporter.typeError(_identifier.location, "Constant variables cannot be assigned to.");
return size_t(-1);
}
else if (requiresStorage)
{
if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
if (var->isConstant())
{
m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on non-constant storage variables.");
return size_t(-1);
}
else if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
{
m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
return size_t(-1);
@@ -647,7 +660,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
return size_t(-1);
}
}
else if (!var->isLocalVariable())
else if (!var->isConstant() && var->isStateVariable())
{
m_errorReporter.typeError(_identifier.location, "Only local variables are supported. To access storage variables, use the _slot and _offset suffixes.");
return size_t(-1);
+40 -2
View File
@@ -629,8 +629,46 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
}
else if (auto variable = dynamic_cast<VariableDeclaration const*>(decl))
{
solAssert(!variable->isConstant(), "");
if (m_context.isStateVariable(decl))
if (variable->isConstant())
{
u256 value;
if (variable->value()->annotation().type->category() == Type::Category::RationalNumber)
{
value = dynamic_cast<RationalNumberType const&>(*variable->value()->annotation().type).literalValue(nullptr);
if (FixedBytesType const* bytesType = dynamic_cast<FixedBytesType const*>(variable->type()))
value = value << (256 - 8 * bytesType->numBytes());
else
solAssert(variable->type()->category() == Type::Category::Integer, "");
}
else if (Literal const* literal = dynamic_cast<Literal const*>(variable->value().get()))
{
TypePointer type = literal->annotation().type;
switch (type->category())
{
case Type::Category::Bool:
case Type::Category::Address:
solAssert(*type == *variable->annotation().type, "");
value = type->literalValue(literal);
break;
case Type::Category::StringLiteral:
{
StringLiteralType const& stringLiteral = dynamic_cast<StringLiteralType const&>(*type);
solAssert(variable->type()->category() == Type::Category::FixedBytes, "");
unsigned const numBytes = dynamic_cast<FixedBytesType const&>(*variable->type()).numBytes();
solAssert(stringLiteral.value().size() <= numBytes, "");
value = u256(h256(stringLiteral.value(), h256::AlignLeft));
break;
}
default:
solAssert(false, "");
}
}
else
solAssert(false, "Invalid constant in inline assembly.");
m_context << value;
}
else if (m_context.isStateVariable(decl))
{
auto const& location = m_context.storageLocationOfVariable(*decl);
if (ref->second.isSlot)