Implement internal functions in storage.

This commit is contained in:
chriseth 2020-11-02 13:05:07 +01:00
parent c83d8fae41
commit 129b095b09
24 changed files with 113 additions and 7 deletions

View File

@ -2463,9 +2463,16 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type, bool _spl
return templ.render(); return templ.render();
} }
bool leftAligned = false;
if (
_type.category() != Type::Category::Function ||
dynamic_cast<FunctionType const&>(_type).kind() == FunctionType::Kind::External
)
leftAligned = _type.leftAligned();
if (storageBytes == 32) if (storageBytes == 32)
templ("cleaned", "value"); templ("cleaned", "value");
else if (_type.leftAligned()) else if (leftAligned)
templ("cleaned", shiftLeftFunction(256 - 8 * storageBytes) + "(value)"); templ("cleaned", shiftLeftFunction(256 - 8 * storageBytes) + "(value)");
else else
templ("cleaned", "and(value, " + toCompactHexWithPrefix((u256(1) << (8 * storageBytes)) - 1) + ")"); templ("cleaned", "and(value, " + toCompactHexWithPrefix((u256(1) << (8 * storageBytes)) - 1) + ")");
@ -2476,7 +2483,8 @@ string YulUtilFunctions::cleanupFromStorageFunction(Type const& _type, bool _spl
string YulUtilFunctions::prepareStoreFunction(Type const& _type) string YulUtilFunctions::prepareStoreFunction(Type const& _type)
{ {
solUnimplementedAssert(_type.category() != Type::Category::Function, ""); if (_type.category() == Type::Category::Function)
solUnimplementedAssert(dynamic_cast<FunctionType const&>(_type).kind() == FunctionType::Kind::Internal, "");
string functionName = "prepare_store_" + _type.identifier(); string functionName = "prepare_store_" + _type.identifier();
return m_functionCollector.createFunction(functionName, [&]() { return m_functionCollector.createFunction(functionName, [&]() {
@ -2703,12 +2711,13 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
_to.identifier(); _to.identifier();
return m_functionCollector.createFunction(functionName, [&]() { return m_functionCollector.createFunction(functionName, [&]() {
return Whiskers(R"( return Whiskers(R"(
function <functionName>(addr, functionId) -> outAddr, outFunctionId { function <functionName>(<?external>addr, </external>functionId) -> <?external>outAddr, </external>outFunctionId {
outAddr := addr <?external>outAddr := addr</external>
outFunctionId := functionId outFunctionId := functionId
} }
)") )")
("functionName", functionName) ("functionName", functionName)
("external", fromType.kind() == FunctionType::Kind::External)
.render(); .render();
}); });
} }

View File

@ -425,7 +425,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
"(" << "(" <<
("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") << ("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") <<
", " << ", " <<
converted.name() << converted.commaSeparatedList() <<
")\n"; ")\n";
} }
} }

View File

@ -41,6 +41,7 @@ contract C {
} }
} }
// ==== // ====
// compileViaYul: also
// EVMVersion: >homestead // EVMVersion: >homestead
// ---- // ----
// g() -> 32, 132, hex"15cfcc01", 32, 32, 1, 42, hex"00000000000000000000000000000000000000000000000000000000" // g() -> 32, 132, hex"15cfcc01", 32, 32, 1, 42, hex"00000000000000000000000000000000000000000000000000000000"

View File

@ -17,6 +17,8 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// one() -> 3 // one() -> 3
// two() -> FAILURE // two() -> FAILURE

View File

@ -5,6 +5,8 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// f(uint256): 0 -> 0x20, 0x4, "This" // f(uint256): 0 -> 0x20, 0x4, "This"
// f(uint256): 1 -> 0x20, 0x2, "is" // f(uint256): 1 -> 0x20, 0x2, "is"

View File

@ -13,5 +13,7 @@ contract C {
return this.h(a); return this.h(a);
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// g() -> 0x0700000000000000000000000000000000000000000000000000000000000000 // g() -> 0x0700000000000000000000000000000000000000000000000000000000000000

View File

@ -16,6 +16,8 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// use(uint256): 3 -> 6 // use(uint256): 3 -> 6
// result_in_constructor() -> 4 // result_in_constructor() -> 4

View File

@ -0,0 +1,25 @@
contract C {
uint16 public result_in_constructor;
function(uint16) returns (uint16) internal x;
uint16 public other = 0x1fff;
constructor() {
x = doubleInv;
result_in_constructor = use(2);
}
function doubleInv(uint16 _arg) public returns (uint16 _ret) {
_ret = ~(_arg * 2);
}
function use(uint16 _arg) public returns (uint16) {
return x(_arg);
}
}
// ====
// compileViaYul: also
// ----
// use(uint16): 3 -> 0xfff9
// result_in_constructor() -> 0xfffb
// other() -> 0x1fff

View File

@ -14,5 +14,7 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// t() -> 7 // t() -> 7

View File

@ -17,5 +17,7 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// t() -> 7 // t() -> 7

View File

@ -16,5 +16,7 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// t() -> FAILURE // t() -> FAILURE

View File

@ -20,6 +20,8 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// set() -> 7 // set() -> 7
// ca() -> 7 // ca() -> 7

View File

@ -6,5 +6,7 @@ contract C {
return [this.f, this.g][0]{value: 1}(); return [this.f, this.g][0]{value: 1}();
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// h(), 1 ether -> 1 // h(), 1 ether -> 1

View File

@ -25,6 +25,8 @@ contract Flow {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// success() -> false // success() -> false
// f() -> 7 // f() -> 7

View File

@ -11,5 +11,7 @@ contract C {
return x + 1; return x + 1;
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// f(uint256): 7 -> 8 // f(uint256): 7 -> 8

View File

@ -14,5 +14,7 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// test() -> true // test() -> true

View File

@ -0,0 +1,34 @@
struct S {
uint16 a;
function() returns (uint) x;
uint16 b;
}
contract Flow {
S[2] t;
function X() internal pure returns (uint) {
return 1;
}
function Y() internal pure returns (uint) {
return 2;
}
constructor() {
t[0].a = 0xff07;
t[0].b = 0xff07;
t[1].x = Y;
t[1].a = 0xff07;
t[1].b = 0xff07;
t[0].x = X;
}
function f() public returns (uint, uint) {
return (t[0].x(), t[1].x());
}
}
// ====
// compileViaYul: also
// ----
// f() -> 1, 2

View File

@ -7,5 +7,7 @@ contract Test {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// f() -> FAILURE // f() -> FAILURE

View File

@ -14,6 +14,8 @@ contract C {
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// g() -> 2 // g() -> 2
// h() -> FAILURE // h() -> FAILURE

View File

@ -32,6 +32,8 @@ contract C {
return (["any", "any"], ["any", "any", "any"]); return (["any", "any"], ["any", "any", "any"]);
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// r() -> true, false, true // r() -> true, false, true
// s() -> 123, 456, 789 // s() -> 123, 456, 789
@ -41,4 +43,3 @@ contract C {
// w2() -> 0x20, 0x40, 0x80, 3, "any", 3, "any" // w2() -> 0x20, 0x40, 0x80, 3, "any", 3, "any"
// w3() -> 0x20, 0x60, 0xa0, 0xe0, 3, "any", 3, "any", 3, "any" // w3() -> 0x20, 0x60, 0xa0, 0xe0, 3, "any", 3, "any", 3, "any"
// x() -> 0x40, 0x0100, 0x40, 0x80, 3, "any", 3, "any", 0x60, 0xa0, 0xe0, 3, "any", 3, "any", 3, "any" // x() -> 0x40, 0x0100, 0x40, 0x80, 3, "any", 3, "any", 0x60, 0xa0, 0xe0, 3, "any", 3, "any", 3, "any"

View File

@ -8,5 +8,7 @@ contract Test {
assert(val[0].vals.length == 42); assert(val[0].vals.length == 42);
} }
} }
// ----- // ====
// compileViaYul: also
// ----
// func() -> // func() ->

View File

@ -35,5 +35,7 @@ contract InvalidTest {
x++; x++;
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// run() -> FAILURE // run() -> FAILURE

View File

@ -14,6 +14,8 @@ contract InvalidTest {
storedFn(); storedFn();
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// f() -> FAILURE // f() -> FAILURE
// f() -> FAILURE // f() -> FAILURE

View File

@ -19,5 +19,7 @@ contract C {
return (a, b); return (a, b);
} }
} }
// ====
// compileViaYul: also
// ---- // ----
// g() -> 5, 6 // g() -> 5, 6