mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Global functions.
This commit is contained in:
parent
f30dc68cdd
commit
c4a43c64c2
11
AST.h
11
AST.h
@ -233,23 +233,20 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pseudo AST node that is used as declaration for "this", "msg", "tx" and "block" when the
|
* Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global
|
||||||
* identifier is encountered. Will never have a valid location in the source code.
|
* functions when such an identifier is encountered. Will never have a valid location in the source code.
|
||||||
*/
|
*/
|
||||||
class MagicVariableDeclaration: public Declaration
|
class MagicVariableDeclaration: public Declaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class VariableKind { THIS, MSG, TX, BLOCK };
|
MagicVariableDeclaration(ASTString const& _name, std::shared_ptr<Type const> const& _type):
|
||||||
MagicVariableDeclaration(VariableKind _kind, ASTString const& _name, std::shared_ptr<Type const> const& _type):
|
Declaration(Location(), std::make_shared<ASTString>(_name)), m_type(_type) {}
|
||||||
Declaration(Location(), std::make_shared<ASTString>(_name)), m_kind(_kind), m_type(_type) {}
|
|
||||||
virtual void accept(ASTVisitor&) override { BOOST_THROW_EXCEPTION(InternalCompilerError()
|
virtual void accept(ASTVisitor&) override { BOOST_THROW_EXCEPTION(InternalCompilerError()
|
||||||
<< errinfo_comment("MagicVariableDeclaration used inside real AST.")); }
|
<< errinfo_comment("MagicVariableDeclaration used inside real AST.")); }
|
||||||
|
|
||||||
std::shared_ptr<Type const> const& getType() const { return m_type; }
|
std::shared_ptr<Type const> const& getType() const { return m_type; }
|
||||||
VariableKind getKind() const { return m_kind; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VariableKind m_kind;
|
|
||||||
std::shared_ptr<Type const> m_type;
|
std::shared_ptr<Type const> m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,6 +160,7 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation)
|
|||||||
|
|
||||||
bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
||||||
{
|
{
|
||||||
|
using Location = FunctionType::Location;
|
||||||
if (_functionCall.isTypeConversion())
|
if (_functionCall.isTypeConversion())
|
||||||
{
|
{
|
||||||
//@todo struct construction
|
//@todo struct construction
|
||||||
@ -184,7 +185,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
if (asserts(arguments.size() == function.getParameterTypes().size()))
|
if (asserts(arguments.size() == function.getParameterTypes().size()))
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
|
|
||||||
if (function.getLocation() == FunctionType::Location::INTERNAL)
|
if (function.getLocation() == Location::INTERNAL)
|
||||||
{
|
{
|
||||||
// Calling convention: Caller pushes return address and arguments
|
// Calling convention: Caller pushes return address and arguments
|
||||||
// Callee removes them and pushes return values
|
// Callee removes them and pushes return values
|
||||||
@ -208,29 +209,57 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
for (unsigned i = 1; i < function.getReturnParameterTypes().size(); ++i)
|
for (unsigned i = 1; i < function.getReturnParameterTypes().size(); ++i)
|
||||||
m_context << eth::Instruction::POP;
|
m_context << eth::Instruction::POP;
|
||||||
}
|
}
|
||||||
else if (function.getLocation() == FunctionType::Location::EXTERNAL)
|
else if (function.getLocation() == Location::EXTERNAL)
|
||||||
{
|
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("External function calls not implemented yet."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("External function calls not implemented yet."));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (function.getLocation())
|
switch (function.getLocation())
|
||||||
{
|
{
|
||||||
case FunctionType::Location::SEND:
|
case Location::SEND:
|
||||||
m_context << u256(0) << u256(0) << u256(0) << u256(0);
|
m_context << u256(0) << u256(0) << u256(0) << u256(0);
|
||||||
arguments.front()->accept(*this);
|
arguments.front()->accept(*this);
|
||||||
//@todo might not be necessary
|
//@todo might not be necessary
|
||||||
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front());
|
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true);
|
||||||
_functionCall.getExpression().accept(*this);
|
_functionCall.getExpression().accept(*this);
|
||||||
m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB
|
m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB
|
||||||
<< eth::Instruction::CALL
|
<< eth::Instruction::CALL
|
||||||
<< eth::Instruction::POP;
|
<< eth::Instruction::POP;
|
||||||
break;
|
break;
|
||||||
case FunctionType::Location::SUICIDE:
|
case Location::SUICIDE:
|
||||||
arguments.front()->accept(*this);
|
arguments.front()->accept(*this);
|
||||||
//@todo might not be necessary
|
//@todo might not be necessary
|
||||||
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front());
|
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true);
|
||||||
m_context << eth::Instruction::SUICIDE;
|
m_context << eth::Instruction::SUICIDE;
|
||||||
|
break;
|
||||||
|
case Location::SHA3:
|
||||||
|
arguments.front()->accept(*this);
|
||||||
|
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true);
|
||||||
|
// @todo move this once we actually use memory
|
||||||
|
m_context << u256(0) << eth::Instruction::MSTORE << u256(32) << u256(0) << eth::Instruction::SHA3;
|
||||||
|
break;
|
||||||
|
case Location::ECRECOVER:
|
||||||
|
case Location::SHA256:
|
||||||
|
case Location::RIPEMD160:
|
||||||
|
{
|
||||||
|
static const map<Location, u256> contractAddresses{{Location::ECRECOVER, 1},
|
||||||
|
{Location::SHA256, 2},
|
||||||
|
{Location::RIPEMD160, 3}};
|
||||||
|
u256 contractAddress = contractAddresses.find(function.getLocation())->second;
|
||||||
|
// @todo later, combine this code with external function call
|
||||||
|
for (unsigned i = 0; i < arguments.size(); ++i)
|
||||||
|
{
|
||||||
|
arguments[i]->accept(*this);
|
||||||
|
appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i], true);
|
||||||
|
// @todo move this once we actually use memory
|
||||||
|
m_context << u256(i * 32) << eth::Instruction::MSTORE;
|
||||||
|
}
|
||||||
|
m_context << u256(32) << u256(0) << u256(arguments.size() * 32) << u256(0) << u256(0)
|
||||||
|
<< contractAddress << u256(500) //@todo determine actual gas requirement
|
||||||
|
<< eth::Instruction::CALL
|
||||||
|
<< eth::Instruction::POP
|
||||||
|
<< u256(0) << eth::Instruction::MLOAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Function not yet implemented."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Function not yet implemented."));
|
||||||
}
|
}
|
||||||
@ -246,9 +275,15 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
|
|||||||
{
|
{
|
||||||
case Type::Category::INTEGER:
|
case Type::Category::INTEGER:
|
||||||
if (member == "balance")
|
if (member == "balance")
|
||||||
|
{
|
||||||
|
appendTypeConversion(*_memberAccess.getExpression().getType(),
|
||||||
|
IntegerType(0, IntegerType::Modifier::ADDRESS), true);
|
||||||
m_context << eth::Instruction::BALANCE;
|
m_context << eth::Instruction::BALANCE;
|
||||||
|
}
|
||||||
else if (member == "send")
|
else if (member == "send")
|
||||||
{ // no modification
|
{
|
||||||
|
appendTypeConversion(*_memberAccess.getExpression().getType(),
|
||||||
|
IntegerType(0, IntegerType::Modifier::ADDRESS), true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer."));
|
||||||
@ -319,7 +354,7 @@ void ExpressionCompiler::endVisit(Identifier& _identifier)
|
|||||||
Declaration* declaration = _identifier.getReferencedDeclaration();
|
Declaration* declaration = _identifier.getReferencedDeclaration();
|
||||||
if (MagicVariableDeclaration* magicVar = dynamic_cast<MagicVariableDeclaration*>(declaration))
|
if (MagicVariableDeclaration* magicVar = dynamic_cast<MagicVariableDeclaration*>(declaration))
|
||||||
{
|
{
|
||||||
if (magicVar->getKind() == MagicVariableDeclaration::VariableKind::THIS)
|
if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this"
|
||||||
m_context << eth::Instruction::ADDRESS;
|
m_context << eth::Instruction::ADDRESS;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,33 @@ namespace solidity
|
|||||||
{
|
{
|
||||||
|
|
||||||
GlobalContext::GlobalContext():
|
GlobalContext::GlobalContext():
|
||||||
m_magicVariables{make_shared<MagicVariableDeclaration>(MagicVariableDeclaration::VariableKind::BLOCK,
|
m_magicVariables{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::BLOCK)),
|
||||||
"block",
|
make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::MSG)),
|
||||||
make_shared<MagicType>(MagicType::Kind::BLOCK)),
|
make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::TX)),
|
||||||
make_shared<MagicVariableDeclaration>(MagicVariableDeclaration::VariableKind::MSG,
|
make_shared<MagicVariableDeclaration>("suicide",
|
||||||
"msg",
|
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(0,
|
||||||
make_shared<MagicType>(MagicType::Kind::MSG)),
|
IntegerType::Modifier::ADDRESS)}),
|
||||||
make_shared<MagicVariableDeclaration>(MagicVariableDeclaration::VariableKind::TX,
|
TypePointers(),
|
||||||
"tx",
|
FunctionType::Location::SUICIDE)),
|
||||||
make_shared<MagicType>(MagicType::Kind::TX))}
|
make_shared<MagicVariableDeclaration>("sha3",
|
||||||
|
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
FunctionType::Location::SHA3)),
|
||||||
|
make_shared<MagicVariableDeclaration>("sha256",
|
||||||
|
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
FunctionType::Location::SHA256)),
|
||||||
|
make_shared<MagicVariableDeclaration>("ecrecover",
|
||||||
|
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH),
|
||||||
|
std::make_shared<IntegerType>(8, IntegerType::Modifier::HASH),
|
||||||
|
std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH),
|
||||||
|
std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
TypePointers({std::make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}),
|
||||||
|
FunctionType::Location::ECRECOVER)),
|
||||||
|
make_shared<MagicVariableDeclaration>("ripemd160",
|
||||||
|
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
|
||||||
|
FunctionType::Location::RIPEMD160))}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +82,6 @@ MagicVariableDeclaration*GlobalContext::getCurrentThis() const
|
|||||||
{
|
{
|
||||||
if (!m_thisPointer[m_currentContract])
|
if (!m_thisPointer[m_currentContract])
|
||||||
m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>(
|
m_thisPointer[m_currentContract] = make_shared<MagicVariableDeclaration>(
|
||||||
MagicVariableDeclaration::VariableKind::THIS,
|
|
||||||
"this", make_shared<ContractType>(*m_currentContract));
|
"this", make_shared<ContractType>(*m_currentContract));
|
||||||
return m_thisPointer[m_currentContract].get();
|
return m_thisPointer[m_currentContract].get();
|
||||||
|
|
||||||
|
2
Types.h
2
Types.h
@ -356,7 +356,7 @@ private:
|
|||||||
class MagicType: public Type
|
class MagicType: public Type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class Kind { BLOCK, MSG, TX }; //@todo should be unified with MagicVariableDeclaration::VariableKind;
|
enum class Kind { BLOCK, MSG, TX };
|
||||||
virtual Category getCategory() const override { return Category::MAGIC; }
|
virtual Category getCategory() const override { return Category::MAGIC; }
|
||||||
|
|
||||||
MagicType(Kind _kind);
|
MagicType(Kind _kind);
|
||||||
|
Loading…
Reference in New Issue
Block a user