Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[yul] Functions: Remove dependency on AST ID. #11512

Merged
merged 1 commit into from Jun 23, 2021
Merged

[yul] Functions: Remove dependency on AST ID. #11512

merged 1 commit into from Jun 23, 2021

Conversation

aarlt
Copy link
Member

@aarlt aarlt commented Jun 10, 2021

Fixes #10342.

@aarlt
Copy link
Member Author

aarlt commented Jun 10, 2021

@chriseth did you mean to fix this issue like this? The current implementation seem to have a problem with structs and mappings. I didn't find the reason yet.

@chriseth
Copy link
Contributor

Yes, this is what I meant, but I'm still not sure if it does not create more problems.

@axic
Copy link
Member

axic commented Jun 14, 2021

How is this solving the core problem? Isn't this just reducing the probability? As long as the order of evaluation matches (even if AST ids are different), this will produce identical results.

How likely is it that the AST ids change, but the order of evaluation remains?

@chriseth
Copy link
Contributor

It at least condenses the IDs.

Copy link
Member

@cameel cameel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semantic tests are failing due to wrong functions being called via pointers so you must have missed one of the .id() calls somewhere.

What about immutable IDs? There's one place in IRGeneratorForStatements that uses AST IDs for them:

define(result) << "loadimmutable(\"" << to_string(_immutable.variable->id()) << "\")\n";

As to the PR overall, looks like it makes the IDs local to the contract being compiled and dependent only on visiting order, which should be stable against adding/removing/reordering input files so I think it's a step in a good direction.

@@ -186,6 +192,8 @@ class IRGenerationContext
/// the code contains a call via a pointer even though a specific function is never assigned to it.
/// It will fail at runtime but the code must still compile.
InternalDispatchMap m_internalDispatchMap;
std::map<int64_t, int64_t> m_functionIds;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a docstring describing what is the key and what is the value.

@@ -150,6 +150,12 @@ class IRGenerationContext
bool inlineAssemblySeen() const { return m_inlineAssemblySeen; }
void setInlineAssemblySeen() { m_inlineAssemblySeen = true; }

int64_t functionId(int64_t _astId) {
if (m_functionIds.find(_astId) == m_functionIds.end())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateInternalDispatchFunctions() rejects functions with ID 0:

// 0 is reserved for uninitialized function pointers
solAssert(function->id() != 0, "Unexpected function ID: 0");

Maybe this assert should be moved (or copied) here?

libsolidity/codegen/ir/IRGenerationContext.h Outdated Show resolved Hide resolved
libsolidity/codegen/ir/IRGenerationContext.h Outdated Show resolved Hide resolved
libsolidity/codegen/ir/IRGenerationContext.h Outdated Show resolved Hide resolved
@cameel
Copy link
Member

cameel commented Jun 16, 2021

@axic

How is this solving the core problem? Isn't this just reducing the probability? As long as the order of evaluation matches (even if AST ids are different), this will produce identical results.

How likely is it that the AST ids change, but the order of evaluation remains?

I think that the biggest problem with IDs was that they change when you compile a different set of input files. E.g. you'd get different IDs when compiling a.sol b.sol than when compiling only b.sol even if the contracts are completely independent. For that case the evaluation order should remain the same. Not sure this PR solves it completely (I think that e.g. immutable IDs are affected by this too) but I think it does at least for internal dispatch.

@chriseth
Copy link
Contributor

I'm now more confident that the IDs generated here are pretty stable. The function generation queue is based on AST IDs, the rest of the code generation is more or less in source order (depends on how sub-nodes are visited), and function IDs are generated when they are first requested, i.e. when a function is referenced.

@chriseth
Copy link
Contributor

This does create a disparity between the AST IDs that are part of the generated yul code (the function names) and the actual values used at runtime. Is that a problem? We have to use AST IDs for function names because we also generate yul functions for external solidity functions or functions that are not referenced and these AST IDs should be stripped in the final IR code anyway.

@chriseth chriseth force-pushed the issue_10342 branch 2 times, most recently from 3e09ab6 to ed51f34 Compare June 22, 2021 16:02
@@ -32,6 +32,6 @@ contract C {
// compileViaYul: also
// ----
// f() -> 42, 23, 34, 42, 42
// gas irOptimized: 111210
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha nice, this reduction is because a PUSH1 87 is replaced by a PUSH1 1 :)

Copy link
Member

@hrkrshnn hrkrshnn Jun 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the diff: https://gist.github.com/hrkrshnn/03381b12959e8f5709a6aadff7cd69da

The difference is from inlining.

@chriseth chriseth requested a review from axic June 23, 2021 11:23
@chriseth
Copy link
Contributor

How is this solving the core problem? Isn't this just reducing the probability? As long as the order of evaluation matches (even if AST ids are different), this will produce identical results.

How likely is it that the AST ids change, but the order of evaluation remains?

Previously, the code changes once you add another source file to the inputs, even if the source file is fully unrelated to the contract being complied.

Now, the code only changes if the current contract references a new internal function for use as a function pointer, so it should be fully independent from "cosmetic" source code changes or compiling all files at the same time / only compiling a single file.

cameel
cameel previously approved these changes Jun 23, 2021
Copy link
Member

@cameel cameel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me.

I have two cosmetic suggestions and one question but nothing critical so approving already.

@chriseth
Copy link
Contributor

Renamed the function.

@chriseth chriseth merged commit cbf1c3a into develop Jun 23, 2021
@chriseth chriseth deleted the issue_10342 branch June 23, 2021 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

In Sol->Yul, the code depends on AST IDs
5 participants