mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Support constant numbers in inline assembly.
This commit is contained in:
parent
b8dbf7d2a8
commit
cdd137e3d1
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
* Inline Assembly: Support direct constants of value type in inline assembly.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -629,14 +629,27 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
|
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||||
{
|
{
|
||||||
solAssert(var->type(), "Expected variable type!");
|
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);
|
return size_t(-1);
|
||||||
}
|
}
|
||||||
else if (requiresStorage)
|
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.");
|
m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
@ -647,7 +660,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
return size_t(-1);
|
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.");
|
m_errorReporter.typeError(_identifier.location, "Only local variables are supported. To access storage variables, use the _slot and _offset suffixes.");
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
|
@ -629,8 +629,46 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
}
|
}
|
||||||
else if (auto variable = dynamic_cast<VariableDeclaration const*>(decl))
|
else if (auto variable = dynamic_cast<VariableDeclaration const*>(decl))
|
||||||
{
|
{
|
||||||
solAssert(!variable->isConstant(), "");
|
if (variable->isConstant())
|
||||||
if (m_context.isStateVariable(decl))
|
{
|
||||||
|
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);
|
auto const& location = m_context.storageLocationOfVariable(*decl);
|
||||||
if (ref->second.isSlot)
|
if (ref->second.isSlot)
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
contract C {
|
||||||
|
uint constant a = 2;
|
||||||
|
bytes2 constant b = 0xabcd;
|
||||||
|
bytes3 constant c = "abc";
|
||||||
|
bool constant d = true;
|
||||||
|
address payable constant e = 0x1212121212121212121212121212121212121212;
|
||||||
|
function f() public pure returns (uint w, bytes2 x, bytes3 y, bool z, address t) {
|
||||||
|
assembly {
|
||||||
|
w := a
|
||||||
|
x := b
|
||||||
|
y := c
|
||||||
|
z := d
|
||||||
|
t := e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// f() -> 2, left(0xabcd), left(0x616263), true, 0x1212121212121212121212121212121212121212
|
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
uint constant x = 2**20;
|
||||||
|
bool constant b = true;
|
||||||
|
bytes4 constant s = "ab";
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
let c1 := x
|
||||||
|
let c2 := b
|
||||||
|
let c3 := s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,10 @@
|
|||||||
|
contract C {
|
||||||
|
string constant x = "abc";
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
let a := x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (115-116): Only direct number constants are supported by inline assembly.
|
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
uint constant x = 2**20;
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
let a := x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
11
test/libsolidity/syntaxTests/inlineAssembly/constant_ref.sol
Normal file
11
test/libsolidity/syntaxTests/inlineAssembly/constant_ref.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
contract C {
|
||||||
|
uint constant a = 2;
|
||||||
|
uint constant b = a;
|
||||||
|
function f() public pure {
|
||||||
|
assembly {
|
||||||
|
let x := b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (134-135): Only direct number constants are supported by inline assembly.
|
@ -1,10 +1,9 @@
|
|||||||
contract test {
|
contract test {
|
||||||
uint constant x = 1;
|
uint constant x = 1;
|
||||||
function f() public {
|
function f() public pure {
|
||||||
assembly {
|
assembly {
|
||||||
let y := x
|
let y := x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (107-108): Constant variables not supported by inline assembly.
|
|
||||||
|
@ -7,4 +7,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (98-99): Constant variables not supported by inline assembly.
|
// TypeError: (98-99): Constant variables cannot be assigned to.
|
||||||
|
@ -7,4 +7,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (112-120): Constant variables not supported by inline assembly.
|
// TypeError: (112-120): The suffixes _offset and _slot can only be used on non-constant storage variables.
|
||||||
|
Loading…
Reference in New Issue
Block a user