Skip to content

Commit 398d1fa

Browse files
committed
Add LinkerObject check and more tests
1 parent 078b141 commit 398d1fa

File tree

5 files changed

+86
-15
lines changed

5 files changed

+86
-15
lines changed

libevmasm/Assembly.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -678,22 +678,30 @@ LinkerObject const& Assembly::assemble() const
678678
if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())
679679
// Append an INVALID here to help tests find miscompilation.
680680
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::INVALID));
681-
681+
682+
map<h256, size_t> subAssemblyOffsets;
683+
map<h256, LinkerObject> subAssemblyLinkerObjects;
684+
for (auto const& [subIdPath, bytecodeOffset]: subRef)
682685
{
683-
std::map<Assembly const*, size_t> subAssemblyOffsets;
684-
for (auto const& [subIdPath, bytecodeOffset]: subRef)
686+
LinkerObject subObject = subAssemblyById(subIdPath)->assemble();
687+
util::h256 h(util::keccak256(util::asString(subObject.bytecode)));
688+
bytesRef r(ret.bytecode.data() + bytecodeOffset, bytesPerDataRef);
689+
size_t* subAssemblyOffset = util::valueOrNullptr(subAssemblyOffsets, h);
690+
LinkerObject* subAssemblyLinkerObject = util::valueOrNullptr(subAssemblyLinkerObjects, h);
691+
692+
// In order for de-duplication to kick in, the bytecode must not only already be present in the
693+
// subAssemblyOffset map, but the LinkerObjects must match as well (linker references, immutable references, etc.)
694+
if (subAssemblyOffset && *subAssemblyLinkerObject == subObject)
695+
toBigEndian(*subAssemblyOffset, r);
696+
else
685697
{
686-
Assembly const* subAssembly = subAssemblyById(subIdPath);
687-
bytesRef r(ret.bytecode.data() + bytecodeOffset, bytesPerDataRef);
688-
if (size_t* subAssemblyOffset = util::valueOrNullptr(subAssemblyOffsets, subAssembly))
689-
toBigEndian(*subAssemblyOffset, r);
690-
else
691-
{
692-
toBigEndian(ret.bytecode.size(), r);
693-
subAssemblyOffsets[subAssembly] = ret.bytecode.size();
694-
ret.append(subAssembly->assemble());
695-
}
698+
toBigEndian(ret.bytecode.size(), r);
699+
subAssemblyOffsets[h] = ret.bytecode.size();
700+
subAssemblyLinkerObjects[h] = subObject;
701+
ret.bytecode += subObject.bytecode;
696702
}
703+
for (auto const& ref: subObject.linkReferences)
704+
ret.linkReferences[ref.first + subAssemblyOffsets[h]] = ref.second;
697705
}
698706
for (auto const& i: tagRef)
699707
{

libevmasm/LinkerObject.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,15 @@ LinkerObject::matchLibrary(
7777
return &it->second;
7878
return nullptr;
7979
}
80+
81+
bool LinkerObject::operator==(LinkerObject const& _other) const
82+
{
83+
return this->bytecode == _other.bytecode &&
84+
this->linkReferences == _other.linkReferences &&
85+
this->immutableReferences == _other.immutableReferences;
86+
}
87+
88+
bool LinkerObject::operator!=(LinkerObject const& _other) const
89+
{
90+
return !(*this == _other);
91+
}

libevmasm/LinkerObject.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ struct LinkerObject
7272
/// of the first 18 bytes of the keccak-256 hash of @a _libraryName.
7373
static std::string libraryPlaceholder(std::string const& _libraryName);
7474

75+
bool operator==(LinkerObject const& _other) const;
76+
bool operator!=(LinkerObject const& _other) const;
77+
7578
private:
7679
static util::h160 const* matchLibrary(
7780
std::string const& _linkRefName,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
library L1 {
2+
function add(uint256 a, uint256 b) external pure returns (uint256) {
3+
return a + b + 1;
4+
}
5+
}
6+
7+
library L2 {
8+
function add(uint256 a, uint256 b) external pure returns (uint256) {
9+
return a + b + 2;
10+
}
11+
}
12+
13+
contract A {
14+
uint256 sum;
15+
constructor() {
16+
sum = L1.add(1, 2);
17+
}
18+
function getSum() external view returns(uint256) {
19+
return sum;
20+
}
21+
}
22+
23+
contract B {
24+
uint256 sum;
25+
constructor() {
26+
sum = L2.add(1, 2);
27+
}
28+
function getSum() external view returns(uint256) {
29+
return sum;
30+
}
31+
}
32+
33+
contract C {
34+
A a = new A();
35+
B b = new B();
36+
function aSum() external view returns(uint256) {
37+
return a.getSum();
38+
}
39+
function bSum() external view returns(uint256) {
40+
return b.getSum();
41+
}
42+
}
43+
44+
// ----
45+
// library: L1
46+
// library: L2
47+
// aSum() -> 4
48+
// bSum() -> 5

test/libyul/objectCompiler/subObjectAccess.yul

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,6 @@ object "A" {
249249
// invalid
250250
// }
251251
// }
252-
// Bytecode: 600060996045603f60866013608560016084600189600055886020558760405586606055856080558460a0558360c0558260e055816101005580610120556101406000f3fe602a6013603d6001603e600185600055846020558360405582606055816080558060a05560c06000f3fe60126001816000558060205560406000f3fefefefefefe60126001816000558060205560406000f3fefe
253-
// Opcodes: PUSH1 0x0 PUSH1 0x99 PUSH1 0x45 PUSH1 0x3F PUSH1 0x86 PUSH1 0x13 PUSH1 0x85 PUSH1 0x1 PUSH1 0x84 PUSH1 0x1 DUP10 PUSH1 0x0 SSTORE DUP9 PUSH1 0x20 SSTORE DUP8 PUSH1 0x40 SSTORE DUP7 PUSH1 0x60 SSTORE DUP6 PUSH1 0x80 SSTORE DUP5 PUSH1 0xA0 SSTORE DUP4 PUSH1 0xC0 SSTORE DUP3 PUSH1 0xE0 SSTORE DUP2 PUSH2 0x100 SSTORE DUP1 PUSH2 0x120 SSTORE PUSH2 0x140 PUSH1 0x0 RETURN INVALID PUSH1 0x2A PUSH1 0x13 PUSH1 0x3D PUSH1 0x1 PUSH1 0x3E PUSH1 0x1 DUP6 PUSH1 0x0 SSTORE DUP5 PUSH1 0x20 SSTORE DUP4 PUSH1 0x40 SSTORE DUP3 PUSH1 0x60 SSTORE DUP2 PUSH1 0x80 SSTORE DUP1 PUSH1 0xA0 SSTORE PUSH1 0xC0 PUSH1 0x0 RETURN INVALID PUSH1 0x12 PUSH1 0x1 DUP2 PUSH1 0x0 SSTORE DUP1 PUSH1 0x20 SSTORE PUSH1 0x40 PUSH1 0x0 RETURN INVALID INVALID INVALID INVALID INVALID INVALID PUSH1 0x12 PUSH1 0x1 DUP2 PUSH1 0x0 SSTORE DUP1 PUSH1 0x20 SSTORE PUSH1 0x40 PUSH1 0x0 RETURN INVALID INVALID
252+
// Bytecode: 600060976045603e60846013608360016083600189600055886020558760405586606055856080558460a0558360c0558260e055816101005580610120556101406000f3fe602a6013603d6001603d600185600055846020558360405582606055816080558060a05560c06000f3fe60126001816000558060205560406000f3fefefefe60126001816000558060205560406000f3fefe
253+
// Opcodes: PUSH1 0x0 PUSH1 0x97 PUSH1 0x45 PUSH1 0x3E PUSH1 0x84 PUSH1 0x13 PUSH1 0x83 PUSH1 0x1 PUSH1 0x83 PUSH1 0x1 DUP10 PUSH1 0x0 SSTORE DUP9 PUSH1 0x20 SSTORE DUP8 PUSH1 0x40 SSTORE DUP7 PUSH1 0x60 SSTORE DUP6 PUSH1 0x80 SSTORE DUP5 PUSH1 0xA0 SSTORE DUP4 PUSH1 0xC0 SSTORE DUP3 PUSH1 0xE0 SSTORE DUP2 PUSH2 0x100 SSTORE DUP1 PUSH2 0x120 SSTORE PUSH2 0x140 PUSH1 0x0 RETURN INVALID PUSH1 0x2A PUSH1 0x13 PUSH1 0x3D PUSH1 0x1 PUSH1 0x3D PUSH1 0x1 DUP6 PUSH1 0x0 SSTORE DUP5 PUSH1 0x20 SSTORE DUP4 PUSH1 0x40 SSTORE DUP3 PUSH1 0x60 SSTORE DUP2 PUSH1 0x80 SSTORE DUP1 PUSH1 0xA0 SSTORE PUSH1 0xC0 PUSH1 0x0 RETURN INVALID PUSH1 0x12 PUSH1 0x1 DUP2 PUSH1 0x0 SSTORE DUP1 PUSH1 0x20 SSTORE PUSH1 0x40 PUSH1 0x0 RETURN INVALID INVALID INVALID INVALID PUSH1 0x12 PUSH1 0x1 DUP2 PUSH1 0x0 SSTORE DUP1 PUSH1 0x20 SSTORE PUSH1 0x40 PUSH1 0x0 RETURN INVALID INVALID
254254
// SourceMappings: 37:15:0:-:0;68:13;97:15;128:13;158:17;192:15;224:17;258:15;291:19;328:17;361:3;358:1;351:14;381:3;377:2;370:15;401:3;397:2;390:15;421:3;417:2;410:15;442:4;437:3;430:17;464:4;459:3;452:17;486:4;481:3;474:17;508:4;503:3;496:17;530:5;525:3;518:18;553:5;548:3;541:18;574:3;571:1;564:14

0 commit comments

Comments
 (0)