Skip to content

Commit

Permalink
[0.8.19] Fix the try-catch lowering hack (#636)
Browse files Browse the repository at this point in the history
  • Loading branch information
abinavpp authored Jun 1, 2024
1 parent d060202 commit 0e65941
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 13 deletions.
7 changes: 7 additions & 0 deletions libsolidity/ast/ASTAnnotations.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,13 @@ struct FunctionCallAnnotation: ExpressionAnnotation
util::SetOnce<FunctionCallKind> kind;
/// If true, this is the external call of a try statement.
bool tryCall = false;

// HACK!
// We track the success tag here for the `TryStatement` lowering. This is to avoid the redundant status check and
// the conditional jump. Such patterns can confuse the zksolc translator.
//
// uint32_t since Assembly::new[Push]Tag() asserts that the tag is 32 bits.
std::optional<uint32_t> tryCallSuccessTag;
};

}
5 changes: 0 additions & 5 deletions libsolidity/codegen/CompilerContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,6 @@ class CompilerContext

RevertStrings revertStrings() const { return m_revertStrings; }

// HACK!
// We track the success tag here for the `TryStatement` lowering. This is to avoid the redundant status check and
// the conditional jump. Such patterns can confuse the zksolc translator.
evmasm::AssemblyItem currTryCallSuccessTag{evmasm::AssemblyItemType::UndefinedItem};

private:
/// Updates source location set in the assembly.
void updateSourceLocation();
Expand Down
12 changes: 9 additions & 3 deletions libsolidity/codegen/ContractCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,10 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
StackHeightChecker checker(m_context);
CompilerContext::LocationSetter locationSetter(m_context, _tryStatement);

compileExpression(_tryStatement.externalCall());
auto* externalCall = dynamic_cast<FunctionCall const*>(&_tryStatement.externalCall());
solAssert(externalCall && externalCall->annotation().tryCall, "");
compileExpression(*externalCall);

int const returnSize = static_cast<int>(_tryStatement.externalCall().annotation().type->sizeOnStack());

// Stack: [ return values] <success flag>
Expand All @@ -1033,8 +1036,11 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)

evmasm::AssemblyItem endTag = m_context.appendJumpToNew();

solAssert(m_context.currTryCallSuccessTag.type() == AssemblyItemType::Tag, "");
m_context << m_context.currTryCallSuccessTag;
auto& successTag = externalCall->annotation().tryCallSuccessTag;
solAssert(successTag, "");
m_context << AssemblyItem(AssemblyItemType::Tag, *successTag);
successTag.reset();

m_context.adjustStackOffset(returnSize);
{
// Success case.
Expand Down
12 changes: 8 additions & 4 deletions libsolidity/codegen/ExpressionCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::External:
case FunctionType::Kind::DelegateCall:
_functionCall.expression().accept(*this);
appendExternalFunctionCall(function, arguments, _functionCall.annotation().tryCall);
appendExternalFunctionCall(
function, arguments, _functionCall.annotation().tryCall, &_functionCall.annotation());
break;
case FunctionType::Kind::BareCallCode:
solAssert(false, "Callcode has been removed.");
Expand Down Expand Up @@ -867,7 +868,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// If this is a try call, return "<address> 1" in the success case and
// "0" in the error case.
AssemblyItem errorCase = m_context.appendConditionalJump();
m_context.currTryCallSuccessTag = m_context.appendJumpToNew();
_functionCall.annotation().tryCallSuccessTag
= m_context.appendJumpToNew().data().convert_to<uint32_t>();
m_context.adjustStackOffset(1);
m_context << errorCase;
}
Expand Down Expand Up @@ -2692,7 +2694,8 @@ void ExpressionCompiler::appendExpOperatorCode(Type const& _valueType, Type cons
void ExpressionCompiler::appendExternalFunctionCall(
FunctionType const& _functionType,
vector<ASTPointer<Expression const>> const& _arguments,
bool _tryCall
bool _tryCall,
FunctionCallAnnotation* _annotation
)
{
solAssert(
Expand Down Expand Up @@ -2982,8 +2985,9 @@ void ExpressionCompiler::appendExternalFunctionCall(

if (_tryCall)
{
solAssert(_annotation, "");
// Success branch will reach this, failure branch will directly jump to endTag.
m_context.currTryCallSuccessTag = m_context.appendJumpToNew();
_annotation->tryCallSuccessTag = m_context.appendJumpToNew().data().convert_to<uint32_t>();
m_context.adjustStackOffset(1);
m_context << endTag;
}
Expand Down
3 changes: 2 additions & 1 deletion libsolidity/codegen/ExpressionCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ class ExpressionCompiler: private ASTConstVisitor
void appendExternalFunctionCall(
FunctionType const& _functionType,
std::vector<ASTPointer<Expression const>> const& _arguments,
bool _tryCall
bool _tryCall,
FunctionCallAnnotation* _annotation = nullptr
);
/// Appends code that evaluates a single expression and moves the result to memory. The memory offset is
/// expected to be on the stack and is updated by this call.
Expand Down

0 comments on commit 0e65941

Please sign in to comment.