Skip to content

Commit

Permalink
Merge pull request #140 from tonlabs/0.70.0
Browse files Browse the repository at this point in the history
0.70.0
  • Loading branch information
IgorKoval authored Jun 19, 2023
2 parents 6953ed5 + 3e3eb04 commit af55112
Show file tree
Hide file tree
Showing 51 changed files with 3,566 additions and 2,085 deletions.
528 changes: 347 additions & 181 deletions API.md

Large diffs are not rendered by default.

237 changes: 127 additions & 110 deletions Cargo.lock

Large diffs are not rendered by default.

73 changes: 71 additions & 2 deletions Changelog_TON.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,76 @@
### 0.70.0 (2023-06-14)

Compiler features:
* Supported [inline assembly](./API.md#assembly).
* Supported overriding `onCodeUpgrade` function.
* Supported [User-defined Value Types](https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types). You can also use this type in public functions.
* [Supported `type(T).min` and `type(T).max`](API.md#type-information).
* New `<TvmBuilder>.store*()` functions:
* `<TvmBuilder>.storeIntLE2()`
* `<TvmBuilder>.storeIntLE4()`
* `<TvmBuilder>.storeIntLE8()`
* `<TvmBuilder>.storeUintLE2()`
* `<TvmBuilder>.storeUintLE4()`
* `<TvmBuilder>.storeUintLE8()`
* New `<TvmSlice>.load*()` functions:
* `<TvmSlice>.loadIntQ()`
* `<TvmSlice>.loadUintQ()`
* `<TvmSlice>.loadSliceQ()`
* `<TvmSlice>.loadIntLE2()`
* `<TvmSlice>.loadIntLE4()`
* `<TvmSlice>.loadIntLE8()`
* `<TvmSlice>.loadUintLE2()`
* `<TvmSlice>.loadUintLE4()`
* `<TvmSlice>.loadUintLE8()`
* `<TvmSlice>.loadIntLE4Q()`
* `<TvmSlice>.loadIntLE8Q()`
* `<TvmSlice>.loadUintLE4Q()`
* `<TvmSlice>.loadUintLE8Q()`
* New `<TvmSlice>.preload*()` functions:
* `<TvmSlice>.preload()`
* `<TvmSlice>.preloadQ()`
* `<TvmSlice>.preloadRef()`
* `<TvmSlice>.preloadInt()`
* `<TvmSlice>.preloadIntQ()`
* `<TvmSlice>.preloadUint()`
* `<TvmSlice>.preloadUintQ()`
* `<TvmSlice>.preloadSlice()`
* `<TvmSlice>.preloadSliceQ()`
* `<TvmSlice>.preloadIntLE4()`
* `<TvmSlice>.preloadIntLE8()`
* `<TvmSlice>.preloadUintLE4()`
* `<TvmSlice>.preloadUintLE8()`
* `<TvmSlice>.preloadIntLE4Q()`
* `<TvmSlice>.preloadIntLE8Q()`
* `<TvmSlice>.preloadUintLE4Q()`
* `<TvmSlice>.preloadUintLE8Q()`
* Supported `variable integer` type in arguments of `math.*` functions.
* Supported conversion `bytes`/`string` <=> `TvmSlice`.

Gas optimizations:
* Assorted stack optimizations.

Bugfixes:
* Fixed compilation fail if you use `<TvmSlice>.loadSlice(l)` where `l` is constant and `l == 0` or `l > 256`.

Other changes:
* Renamed some functions. Old functions are available and marked as deprecated. Renaming:
* `<TvmSlice>.decode()` -> `<TvmSlice>.load()`
* `<TvmSlice>.decodeQ()` -> `<TvmSlice>.loadQ()`
* `<TvmSlice>.decodeFunctionParams()` -> `<TvmSlice>.loadFunctionParams()`
* `<TvmSlice>.decodeStateVars()` -> `<TvmSlice>.loadStateVars()`
* `<TvmSlice>.loadSigned()` -> `<TvmSlice>.loadInt()`
* `<TvmSlice>.loadUnsigned()` -> `<TvmSlice>.loadUint()`
* `<TvmBuilder>.storeSigned()` -> `<TvmSlice>.storeInt()`
* `<TvmBuilder>.storeUnsigned()` -> `<TvmSlice>.storeUint()`
* Improved `try-catch` (experimental feature).
* Now `tx.storageFee` returns `uint120` (not `uint64`).
* Renamed `tx.timestamp` to `tx.logicaltime`. `tx.timestamp` is available and marked as deprecated.

### 0.69.0 (2023-05-15)

Breaking changes:
* `pragma AbiHeader time` is no longer allowed for use. Timestamp in header of external message is enabled by default and can be disabled with `pragma AbiHeader notime`.
* `pragma AbiHeader time` is no longer allowed for use. Timestamp in header of external message is enabled by default and can be disabled with `pragma AbiHeader notime`.

Compiler features:
* Supported generating code for The Open Network. Use command line option `--tvm-version ton`. We don't use `ZERO(SWAP|ROTR)IF[NOT][2]`, `COPYLEFT`, `INITCODEHASH`, `MYCODE`, `STORAGEFEE`, `LDCONT`, `STCONT` and another opcodes for ton.
Expand All @@ -10,7 +79,7 @@ Optimizations:
* Improved constant analyzer that compile more optimal code for `require`/`revert` functions and another cases.

Bugfixes:
* Fixed segmentation fault that could occur in some cases of using `var[U]Int` types.
* Fixed segmentation fault that could occur in some cases of using `variable integer` types.
* Fixed segmentation fault that occurred in constructions `optional(T1, T2) x = null;` and some another cases.

### 0.68.0 (2023-04-19)
Expand Down
2 changes: 1 addition & 1 deletion compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ include(EthPolicy)
eth_policy()

# project name and version should be set after cmake_policy CMP0048
set(PROJECT_VERSION "0.69.0")
set(PROJECT_VERSION "0.70.0")
# OSX target needed in order to support std::visit
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
Expand Down
7 changes: 3 additions & 4 deletions compiler/libsolidity/analysis/ControlFlowBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,9 @@ bool ControlFlowBuilder::visit(Conditional const& _conditional)

bool ControlFlowBuilder::visit(TryStatement const& _tryStatement)
{
appendControlFlow(_tryStatement.body());

auto nodes = splitFlow(1);
nodes[0] = createFlow(nodes[0], _tryStatement.clause().block());
auto nodes = splitFlow(2);
nodes[0] = createFlow(nodes[0], _tryStatement.body());
nodes[1] = createFlow(nodes[1], _tryStatement.clause());
mergeFlow(nodes);

return false;
Expand Down
21 changes: 12 additions & 9 deletions compiler/libsolidity/analysis/StaticAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,23 @@ bool StaticAnalyzer::visit(FunctionDefinition const& _function)
return true;
}

void StaticAnalyzer::endVisit(FunctionDefinition const&)
void StaticAnalyzer::endVisit(FunctionDefinition const& _funDefinition)
{
if (m_currentFunction && !m_currentFunction->body().statements().empty())
for (auto const& var: m_localVarUseCount)
if (var.second == 0)
{
if (var.first.second->isCallableOrCatchParameter())
m_errorReporter.warning(
5667_error,
var.first.second->location(),
"Unused " +
string(var.first.second->isTryCatchParameter() ? "try/catch" : "function") +
" parameter. Remove or comment out the variable name to silence this warning."
);
if (var.first.second->isCallableOrCatchParameter()) {
if (!_funDefinition.isInlineAssembly()) {
m_errorReporter.warning(
5667_error,
var.first.second->location(),
"Unused " +
string(var.first.second->isTryCatchParameter() ? "try/catch" : "function") +
" parameter. Remove or comment out the variable name to silence this warning."
);
}
}
else
m_errorReporter.warning(2072_error, var.first.second->location(), "Unused local variable.");
}
Expand Down
39 changes: 25 additions & 14 deletions compiler/libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ TypePointers TypeChecker::typeCheckMetaTypeFunctionAndRetrieveReturnType(Functio
wrongType = contractType->isSuper();
else if (
typeCategory != Type::Category::Integer &&
typeCategory != Type::Category::VarInteger &&
typeCategory != Type::Category::Enum
)
wrongType = true;
Expand Down Expand Up @@ -719,6 +720,14 @@ bool TypeChecker::isBadAbiType(
case Type::Category::VarInteger:
break;

case Type::Category::UserDefinedValueType: {
auto userDefType = dynamic_cast<UserDefinedValueType const*>(curType);
if (isBadAbiType(origVarLoc, &userDefType->underlyingType(), curVarLoc, usedStructs, doPrintErr)) {
return true;
}
break;
}

default: {
printError("ABI doesn't support " + curType->toString() + " type.");
return true;
Expand Down Expand Up @@ -757,8 +766,8 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (!_function.modifiers().empty() && _function.isFree())
m_errorReporter.syntaxError(5811_error, _function.location(), "Free functions cannot have modifiers.");

if (_function.externalMsg() || _function.internalMsg()) {
if (_function.externalMsg() && _function.internalMsg()) {
if (_function.isExternalMsg() || _function.isInternalMsg()) {
if (_function.isExternalMsg() && _function.isInternalMsg()) {
m_errorReporter.typeError(228_error, _function.location(), R"("internalMsg" and "externalMsg" cannot be used together.)");
}
if (!_function.functionIsExternallyVisible()) {
Expand Down Expand Up @@ -1152,9 +1161,9 @@ void TypeChecker::endVisit(TryStatement const& _tryStatement)

auto printError = [&](SourceLocation const& loc){
m_errorReporter.typeError(
228_error,
loc,
"Expected `catch (variant value, uint number) { ... }`.");
228_error,
loc,
"Expected `catch (variant value, uint number) { ... }`.");
};
if (errArgs.size() != 2) {
printError(clause.location());
Expand All @@ -1163,7 +1172,7 @@ void TypeChecker::endVisit(TryStatement const& _tryStatement)
if (*errArgs.at(0)->type() != *TypeProvider::variant()) {
printError(errArgs.at(0)->location());
}
if (*errArgs.at(1)->type() != *TypeProvider::uint256()) {
if (*errArgs.at(1)->type() != *TypeProvider::uint(16)) {
printError(errArgs.at(1)->location());
}
}
Expand Down Expand Up @@ -3350,11 +3359,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)

for (const auto & arg : arguments) {
Type::Category cat = arg->annotation().type->mobileType()->category();
if (cat != Type::Category::Integer) {
if (cat != Type::Category::Integer && cat != Type::Category::VarInteger) {
m_errorReporter.fatalTypeError(
228_error,
arg->location(),
"Expected an integer type."
"Expected an integer or variable integer type."
);
}
}
Expand All @@ -3376,11 +3385,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)

for (const auto & arg : arguments) {
Type::Category cat = arg->annotation().type->mobileType()->category();
if (cat != Type::Category::Integer && cat != Type::Category::FixedPoint) {
if (cat != Type::Category::Integer && cat != Type::Category::FixedPoint && cat != Type::Category::VarInteger) {
m_errorReporter.fatalTypeError(
228_error,
arg->location(),
"Expected integer or fixed point type."
"Expected integer, variable integer or fixed point type."
);
}
}
Expand Down Expand Up @@ -3491,13 +3500,15 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = checkSliceDecode(arguments);
break;
}
case FunctionType::Kind::TVMSliceDecode:
case FunctionType::Kind::TVMSliceLoad:
case FunctionType::Kind::TVMSlicePreload:
{
checkAtLeastOneArg();
returnTypes = checkSliceDecode(_functionCall.arguments());
break;
}
case FunctionType::Kind::TVMSliceDecodeQ:
case FunctionType::Kind::TVMSliceLoadQ:
case FunctionType::Kind::TVMSlicePreloadQ:
{
checkAtLeastOneArg();
TypePointers members = checkSliceDecode(_functionCall.arguments()); // TODO make for Q
Expand All @@ -3512,7 +3523,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = getReturnTypesForTVMConfig(_functionCall);
break;
}
case FunctionType::Kind::DecodeFunctionParams:
case FunctionType::Kind::TVMSliceLoadFunctionParams:
{
if (arguments.size() != 1) {
m_errorReporter.fatalTypeError(
Expand Down Expand Up @@ -3563,7 +3574,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = functionType->returnParameterTypes();
break;
}
case FunctionType::Kind::TVMSliceDecodeStateVars:
case FunctionType::Kind::TVMSliceLoadStateVars:
{
if (arguments.size() != 1) {
m_errorReporter.fatalTypeError(
Expand Down
8 changes: 5 additions & 3 deletions compiler/libsolidity/analysis/ViewPureChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ bool ViewPureChecker::visit(FunctionDefinition const& _funDef)
"Library functions must have default mutability. Delete keyword view or pure.");
}
}
if (_funDef.isFree() && _funDef.stateMutability() != StateMutability::NonPayable) {
if (_funDef.isFree() && !_funDef.isInlineAssembly() && _funDef.stateMutability() != StateMutability::NonPayable) {
m_errorReporter.warning(228_error, _funDef.location(),
"Free functions must have default mutability. Delete keyword view or pure.");
}
Expand Down Expand Up @@ -82,7 +82,8 @@ void ViewPureChecker::endVisit(FunctionDefinition const& _funDef)
!_funDef.isFree() &&
!_funDef.isFallback() &&
!_funDef.isReceive() &&
!_funDef.virtualSemantics()
!_funDef.virtualSemantics() &&
!_funDef.isInlineAssembly()
)
m_errorReporter.warning(
2018_error,
Expand Down Expand Up @@ -264,7 +265,7 @@ void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
auto ident = dynamic_cast<Identifier const*>(&_functionCall.expression());
if (ident) {
auto funcDef = dynamic_cast<FunctionDefinition const*>(ident->annotation().referencedDeclaration);
isFree = funcDef && funcDef->isFree();
isFree = funcDef && funcDef->isFree() && !funcDef->isInlineAssembly();
}
if (isFree)
mutability = StateMutability::Pure;
Expand Down Expand Up @@ -412,6 +413,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
{MagicType::Kind::TVM, "setGasLimit"},
{MagicType::Kind::TVM, "setcode"},
{MagicType::Kind::TVM, "stateInitHash"},
{MagicType::Kind::Transaction, "logicaltime"},
{MagicType::Kind::Transaction, "storageFee"},
{MagicType::Kind::Transaction, "timestamp"},
};
Expand Down
5 changes: 5 additions & 0 deletions compiler/libsolidity/ast/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,11 @@ StatementAnnotation& Statement::annotation() const
return initAnnotation<StatementAnnotation>();
}

StatementAnnotation& FreeInlineAssembly::annotation() const
{
return initAnnotation<StatementAnnotation>();
}

InlineAssemblyAnnotation& InlineAssembly::annotation() const
{
return initAnnotation<InlineAssemblyAnnotation>();
Expand Down
43 changes: 32 additions & 11 deletions compiler/libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -930,11 +930,12 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
std::vector<ASTPointer<ModifierInvocation>> _modifiers,
ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body,
std::optional<uint32_t> _functionID = {},
bool _isInline = false,
bool _responsible = false,
bool _externalMsg = false,
bool _internalMsg = false
std::optional<uint32_t> _functionID,
bool _isInline,
bool _responsible,
bool _externalMsg,
bool _internalMsg,
bool _freeInlineAssembly
):
CallableDeclaration(_id, _location, _name, std::move(_nameLocation), _visibility, _parameters, _isVirtual, _overrides, _returnParameters),
StructurallyDocumented(_documentation),
Expand All @@ -945,10 +946,11 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
m_functionModifiers(std::move(_modifiers)),
m_body(_body),
m_functionID(_functionID),
m_isInline(_isInline),
m_inline(_isInline),
m_responsible{_responsible},
m_externalMsg{_externalMsg},
m_internalMsg{_internalMsg}
m_internalMsg{_internalMsg},
m_inlineAssembly{_freeInlineAssembly}
{
solAssert(_kind == Token::Constructor || _kind == Token::Function ||
_kind == Token::Fallback || _kind == Token::Receive || _kind == Token::onBounce ||
Expand Down Expand Up @@ -1015,10 +1017,11 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
}

std::optional<uint32_t> functionID() const { return m_functionID; }
bool isInline() const { return m_isInline; }
bool isInline() const { return m_inline; }
bool isResponsible() const { return m_responsible; }
bool externalMsg() const { return m_externalMsg; }
bool internalMsg() const { return m_internalMsg; }
bool isExternalMsg() const { return m_externalMsg; }
bool isInternalMsg() const { return m_internalMsg; }
bool isInlineAssembly() const { return m_inlineAssembly; }
FunctionDefinition const& resolveVirtual(
ContractDefinition const& _mostDerivedContract,
ContractDefinition const* _searchStart = nullptr
Expand All @@ -1031,10 +1034,11 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
ASTPointer<Block> m_body;
std::optional<uint32_t> m_functionID;
bool m_isInline;
bool m_inline{};
bool m_responsible{};
bool m_externalMsg{};
bool m_internalMsg{};
bool m_inlineAssembly{};
};

/**
Expand Down Expand Up @@ -1558,6 +1562,23 @@ class Statement: public ASTNode, public Documented
StatementAnnotation& annotation() const override;
};

class FreeInlineAssembly: public Statement
{
public:
explicit FreeInlineAssembly(
int64_t _id,
SourceLocation const& _location,
ASTPointer<ASTString> const& _docString,
std::vector<ASTPointer<Expression>> _lines
): Statement(_id, _location, _docString), m_lines{_lines} {}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;
StatementAnnotation& annotation() const override;
std::vector<ASTPointer<Expression>> const& lines() const { return m_lines; }
private:
std::vector<ASTPointer<Expression>> m_lines;
};

/**
* Inline assembly.
*/
Expand Down
Loading

0 comments on commit af55112

Please sign in to comment.