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

0.24 #13

Merged
merged 1 commit into from
May 7, 2020
Merged

0.24 #13

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
724 changes: 724 additions & 0 deletions API.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion compiler/libsolidity/analysis/GlobalContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ int magicVariableToID(std::string const& _name)
else if (_name == "log2") return -12;
else if (_name == "log3") return -13;
else if (_name == "log4") return -14;
else if (_name == "logtvm") return -101;
else if (_name == "logtvm") return -102;
else if (_name == "msg") return -15;
else if (_name == "mulmod") return -16;
else if (_name == "now") return -17;
Expand Down
36 changes: 36 additions & 0 deletions compiler/libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2401,6 +2401,42 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
}
break;
}
case FunctionType::Kind::TVMMaxMin:
{
if (arguments.size() < 2) {
m_errorReporter.fatalTypeError(
_functionCall.location(),
"This function takes at least two arguments."
);
}

auto isIntegerType = [this](ASTPointer<Expression const> arg){
Type::Category cat = arg->annotation().type->category();
if (cat != Type::Category::Integer && cat != Type::Category::RationalNumber) {
m_errorReporter.fatalTypeError(
arg->location(),
"Argument must have integer type."
);
}
};
for (std::size_t i = 0; i < arguments.size(); ++i) {
isIntegerType(arguments.at(i));
}

TypePointer result = arguments.at(0)->annotation().type;
for (std::size_t i = 1; i < arguments.size(); ++i) {
TypePointer rightType = arguments.at(i)->annotation().type;
result = Type::commonType(result, rightType);
if (result == nullptr) {
m_errorReporter.fatalTypeError(
arguments.at(i)->location(),
"All arguments must have signed or unsigned at the same time."
);
}
}
returnTypes.push_back(result);
break;
}
case FunctionType::Kind::ABIEncode:
case FunctionType::Kind::ABIEncodePacked:
case FunctionType::Kind::ABIEncodeWithSelector:
Expand Down
2 changes: 2 additions & 0 deletions compiler/libsolidity/analysis/ViewPureChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,8 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
{MagicType::Kind::TVM, "setExtDestAddr"},
{MagicType::Kind::TVM, "transfer"},
{MagicType::Kind::TVM, "transLT"},
{MagicType::Kind::TVM, "min"},
{MagicType::Kind::TVM, "max"},
{MagicType::Kind::MetaType, "creationCode"},
{MagicType::Kind::MetaType, "runtimeCode"},
{MagicType::Kind::MetaType, "name"},
Expand Down
18 changes: 17 additions & 1 deletion compiler/libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2827,6 +2827,7 @@ string FunctionType::richIdentifier() const
case Kind::TVMBuilderMethods: id += "tvmbuildermethods"; break;
case Kind::TVMLoadRef: id += "tvmloadref"; break;
case Kind::TVMFunctionId: id += "tvmfunctionid"; break;
case Kind::TVMMaxMin: id += "tvmmaxmin"; break;
case Kind::AddressMakeAddrStd: id += "addressmakeaddrstd"; break;
case Kind::LogTVM: id += "logtvm"; break;
case Kind::MappingGetMinKey: id += "mapgetmin"; break;
Expand Down Expand Up @@ -3966,7 +3967,22 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
FunctionType::Kind::TVMFunctionId,
true, StateMutability::Pure
));

members.emplace_back("max", TypeProvider::function(
TypePointers{},
TypePointers{},
strings{},
strings{},
FunctionType::Kind::TVMMaxMin,
true, StateMutability::Pure
));
members.emplace_back("min", TypeProvider::function(
TypePointers{},
TypePointers{},
strings{},
strings{},
FunctionType::Kind::TVMMaxMin,
true, StateMutability::Pure
));
return members;
}
case Kind::Transaction:
Expand Down
1 change: 1 addition & 0 deletions compiler/libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,7 @@ class FunctionType: public Type
TVMDeploy, ///< functions to deploy contract from contract
TVMDestAddr, ///< tvm.setExtDestAddr()
TVMFunctionId, ///< tvm.functionId(function_name)
TVMMaxMin, ///< tvm.min(a, b, ...) or tvm.max(a, b, ...)
TVMHash, ///< tvm.hash()
TVMPubkey, ///< tvm.pubkey()
TVMResetStorage, ///< tvm.resetStorage()
Expand Down
1 change: 1 addition & 0 deletions compiler/libsolidity/codegen/ExpressionCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::TVMDeploy:
case FunctionType::Kind::TVMDestAddr:
case FunctionType::Kind::TVMFunctionId:
case FunctionType::Kind::TVMMaxMin:
case FunctionType::Kind::TVMHash:
case FunctionType::Kind::TVMLoadRef:
case FunctionType::Kind::TVMPubkey:
Expand Down
40 changes: 34 additions & 6 deletions compiler/libsolidity/codegen/TVMABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ DecodePosition::Algo DecodePositionAbiV1::updateStateAndGetLoadAlgo(Type const *
maxRestSliceBits = TvmConst::CellBitLength - size.minBits;
minUsedRef = size.minRefs;
maxUsedRef = size.maxRefs;
return NeedLoadNextCell;
return LoadNextCell;
}

return JustLoad;
Expand All @@ -387,6 +387,7 @@ void Position::loadRef() {
usedRefs = 1;
++idCell;
}
solAssert(usedRefs <= 3, "");
}

int Position::cellNumber() const {
Expand Down Expand Up @@ -427,12 +428,18 @@ DecodePosition::Algo DecodePositionAbiV2::updateStateAndGetLoadAlgo(Type const *
solAssert(0 <= size.minBits && size.minBits <= size.maxBits, "");

if (curTypeIndex == lastRefType) {
minPos.loadRef();
maxPos.loadRef();
if (curTypeIndex + 1 == static_cast<int>(types.size())) {
minPos.loadRef();
maxPos.loadRef();
return JustLoad;
} else {
return CheckBits;
int prevMinCellNumber = minPos.cellNumber();
minPos.loadRef();
maxPos.loadRef();
if (prevMinCellNumber == minPos.cellNumber() && minPos.cellNumber() == maxPos.cellNumber()) {
return JustLoad;
}
return CheckBitsAndRefs;
}
}

Expand All @@ -448,7 +455,7 @@ DecodePosition::Algo DecodePositionAbiV2::updateStateAndGetLoadAlgo(Type const *
if (prevMinCellNumber == prevMaxCellNumber &&
prevMinCellNumber + 1 == minPos.cellNumber() &&
minPos.cellNumber() == maxPos.cellNumber()) {
return NeedLoadNextCell;
return LoadNextCell;
}

if ((type->category() == Type::Category::Array && to<ArrayType>(type)->isByteArray()) ||
Expand Down Expand Up @@ -543,12 +550,29 @@ IF
)");
}

void DecodeFunctionParams::checkBitsAndRefsAndLoadNextSlice() {
// check that bits==0 and ref==1
pusher->pushLines(R"(DUP
SBITREFS
EQINT 1
SWAP
EQINT 0
AND
PUSHCONT {
LDREF
ENDS
CTOS
}
IF
)");
}

void DecodeFunctionParams::loadNextSliceIfNeed(const DecodePosition::Algo algo, VariableDeclaration const *variable,
bool isRefType) {
switch (algo) {
case DecodePosition::JustLoad:
break;
case DecodePosition::NeedLoadNextCell:
case DecodePosition::LoadNextCell:
loadNextSlice();
break;
case DecodePosition::CheckBits:
Expand All @@ -557,6 +581,9 @@ void DecodeFunctionParams::loadNextSliceIfNeed(const DecodePosition::Algo algo,
case DecodePosition::CheckRefs:
checkRefsAndLoadNextSlice();
break;
case DecodePosition::CheckBitsAndRefs:
checkBitsAndRefsAndLoadNextSlice();
break;
case DecodePosition::Unknown:
if (isRefType) {
cast_error(*variable, "Too much refs types");
Expand Down Expand Up @@ -663,6 +690,7 @@ bool EncodePosition::updateState(int i) {

restSliceBits -= size.maxBits;
restFef -= size.maxRefs;
solAssert(restFef >= 0, "");

if (i == lastRefType && restFef == 0 && i + 1 == static_cast<int>(types.size())) {
return false;
Expand Down
3 changes: 2 additions & 1 deletion compiler/libsolidity/codegen/TVMABI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class TVMABI {

class DecodePosition : private boost::noncopyable {
public:
enum Algo {JustLoad, NeedLoadNextCell, CheckBits, CheckRefs, Unknown};
enum Algo {JustLoad, LoadNextCell, CheckBits, CheckRefs, CheckBitsAndRefs, Unknown};
virtual ~DecodePosition() = default;
virtual Algo updateStateAndGetLoadAlgo(Type const* type) = 0;
};
Expand Down Expand Up @@ -99,6 +99,7 @@ class DecodeFunctionParams : private boost::noncopyable {
void loadNextSlice();
void checkBitsAndLoadNextSlice();
void checkRefsAndLoadNextSlice();
void checkBitsAndRefsAndLoadNextSlice();
void loadNextSliceIfNeed(const DecodePosition::Algo algo, VariableDeclaration const* variable, bool isRefType);
void loadq(const DecodePosition::Algo algo, const std::string& opcodeq, const std::string& opcode);
void decodeParameter(VariableDeclaration const* variable, DecodePosition* position);
Expand Down
74 changes: 29 additions & 45 deletions compiler/libsolidity/codegen/TVMFunctionCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,22 +880,14 @@ bool FunctionCallCompiler::checkForTvmFunction(const MemberAccess &_node, Type::
if (_node.memberName() == "cdatasize") { // tvm.cdatasize(cell, uint)
pushArgs();
m_pusher.push(-2 + 3, "CDATASIZE");
return true;
}
if (_node.memberName() == "pubkey") { // tvm.pubkey
} else if (_node.memberName() == "pubkey") { // tvm.pubkey
m_pusher.push(+1, "GETGLOB 2");
return true;
}
if (_node.memberName() == "accept") { // tvm.accept
} else if (_node.memberName() == "accept") { // tvm.accept
m_pusher.push(0, "ACCEPT");
return true;
}
if (_node.memberName() == "hash") { // tvm.hash
} else if (_node.memberName() == "hash") { // tvm.hash
pushArgs();
m_pusher.push(0, "HASHCU");
return true;
}
if (_node.memberName() == "checkSign") { // tvm.checkSign
} else if (_node.memberName() == "checkSign") { // tvm.checkSign
acceptExpr(arguments[0].get());
m_pusher.push(+1, "NEWC");
acceptExpr(arguments[1].get());
Expand All @@ -905,60 +897,52 @@ bool FunctionCallCompiler::checkForTvmFunction(const MemberAccess &_node, Type::
m_pusher.push(0, "ENDC CTOS");
acceptExpr(arguments[3].get());
m_pusher.push(-3+1, "CHKSIGNU");
return true;
}
if (_node.memberName() == "setcode") { // tvm.setcode
} else if (_node.memberName() == "setcode") { // tvm.setcode
pushArgs();
m_pusher.push(-1, "SETCODE");
return true;
}
if (_node.memberName() == "setCurrentCode") { // tvm.setCurrentCode
} else if (_node.memberName() == "setCurrentCode") { // tvm.setCurrentCode
pushArgs();
m_pusher.push(-1+1, "CTOS");
m_pusher.push(0, "BLESS");
m_pusher.push(-1, "POP c3");
return true;
}
if (_node.memberName() == "commit") { // tvm.commit
} else if (_node.memberName() == "commit") { // tvm.commit
m_pusher.pushPrivateFunctionOrMacroCall(0, "c7_to_c4");
m_pusher.push(0, "COMMIT");
return true;
}
if (_node.memberName() == "log") { // tvm.log
} else if (_node.memberName() == "log") { // tvm.log
auto logstr = arguments[0].get();
if (auto literal = to<Literal>(logstr)) {
if (literal->value().length() > 15)
cast_error(_node, "logtvm param should no more than 15 chars");
if (TVMContractCompiler::g_without_logstr) {
return true;
cast_error(_node, "Parameter string should have length no more than 15 chars");
if (!TVMContractCompiler::g_without_logstr) {
m_pusher.push(0, "PRINTSTR " + literal->value());
}
m_pusher.push(0, "PRINTSTR " + literal->value());
} else {
cast_error(_node, "tvm.log() param should be literal");
cast_error(_node, "Parameter should be a literal");
}
return true;
}
if (_node.memberName() == "transLT") { // tvm.transLT
} else if (_node.memberName() == "transLT") { // tvm.transLT
pushArgs();
m_pusher.push(+1, "LTIME");
return true;
}
if (_node.memberName() == "resetStorage") { //tvm.resetStorage
} else if (_node.memberName() == "resetStorage") { //tvm.resetStorage
m_pusher.resetAllStateVars();
return true;
}
if (_node.memberName() == "setExtDestAddr") {
} else if (_node.memberName() == "setExtDestAddr") {
pushArgs();
m_pusher.push(-1, "SETGLOB " + toString(TvmConst::C7::ExtDestAddrIndex));
return true;
}
if (_node.memberName() == "functionId") { // tvm.functionId
} else if (_node.memberName() == "functionId") { // tvm.functionId
auto callDef = getCallableDeclaration(arguments.at(0).get());
EncodeFunctionParams encoder(&m_pusher);
m_pusher.push(+1, "PUSHINT " + to_string(encoder.calculateFunctionID(callDef) & 0x7fffffff));
return true;
} else if (_node.memberName() == "max") {
pushArgs();
for (int i = 0; i + 1 < static_cast<int>(arguments.size()); ++i)
m_pusher.push(-2 + 1, "MAX");
} else if (_node.memberName() == "min") {
pushArgs();
for (int i = 0; i + 1 < static_cast<int>(arguments.size()); ++i)
m_pusher.push(-2 + 1, "MIN");
} else {
return false;
}
return false;
return true;
}

bool FunctionCallCompiler::checkForMemberAccessTypeType(MemberAccess const &_node, Type::Category category) {
Expand Down Expand Up @@ -1215,13 +1199,13 @@ bool FunctionCallCompiler::checkForIdentifier(FunctionCall const &_functionCall)
auto logstr = arguments[0].get();
if (auto literal = to<Literal>(logstr)) {
if (literal->value().length() > 15)
cast_error(_functionCall, "logtvm param should no more than 15 chars");
cast_error(_functionCall, "Parameter string should have length no more than 15 chars");
if (TVMContractCompiler::g_without_logstr) {
return true;
}
m_pusher.push(0, "PRINTSTR " + literal->value());
} else {
cast_error(_functionCall, "logtvm param should be literal");
cast_error(_functionCall, "Parameter should be a literal");
}
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ Allowed options)",
(g_argNatspecDev.c_str(), "Natspec developer documentation of all contracts.")
// (g_argMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.")
(g_argTvm.c_str(), "Produce TVM assembly (deprecated).")
(g_argTvmWithoutLogStr.c_str(), "Intrisic logstr(...) won't produce log strings")
(g_argTvmWithoutLogStr.c_str(), "Ignore tvm.log(string) and logtvm(string)")
(g_argTvmABI.c_str(), "Produce JSON ABI for contract (deprecated).")
(g_argTvmDumpStorage.c_str(), "Dump state vars")
(g_argTvmPeephole.c_str(), "Run peephole optimization pass")
Expand Down Expand Up @@ -888,7 +888,7 @@ Allowed options)",
serr() << " solc contract.sol" << endl;
serr() << "This command compiles the contract and generates contract.code and contract.abi.json files." << endl;
}

if (m_args.count(g_argTvmPeephole)) {
for (int i = 1; i < _argc; i++) {
string s = _argv[i];
Expand Down