aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/ABIFunctions.cpp37
-rw-r--r--libsolidity/codegen/ABIFunctions.h6
-rw-r--r--libsolidity/codegen/ArrayUtils.cpp3
-rw-r--r--libsolidity/codegen/CompilerContext.cpp21
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp14
5 files changed, 49 insertions, 32 deletions
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp
index 756148e7..080be359 100644
--- a/libsolidity/codegen/ABIFunctions.cpp
+++ b/libsolidity/codegen/ABIFunctions.cpp
@@ -87,7 +87,7 @@ string ABIFunctions::tupleEncoder(
);
elementTempl("values", valueNames);
elementTempl("pos", to_string(headPos));
- elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, false));
+ elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, true));
encodeElements += elementTempl.render();
headPos += dynamic ? 0x20 : _targetTypes[i]->calldataEncodedSize();
}
@@ -371,7 +371,7 @@ string ABIFunctions::abiEncodingFunction(
Type const& _from,
Type const& _to,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
)
{
solUnimplementedAssert(
@@ -415,7 +415,7 @@ string ABIFunctions::abiEncodingFunction(
dynamic_cast<FunctionType const&>(_from),
to,
_encodeAsLibraryTypes,
- _compacted
+ _fromStack
);
solAssert(_from.sizeOnStack() == 1, "");
@@ -542,7 +542,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
mstore(pos, sub(tail, headStart))
tail := <encodeToMemoryFun>(<arrayElementAccess>, tail)
srcPtr := <nextArrayElement>(srcPtr)
- pos := add(pos, <elementEncodedSize>)
+ pos := add(pos, 0x20)
}
pos := tail
<assignEnd>
@@ -580,7 +580,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
*_from.baseType(),
*_to.baseType(),
_encodeAsLibraryTypes,
- true
+ false
));
templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" );
templ("nextArrayElement", nextArrayElementFunction(_from));
@@ -729,7 +729,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
*_from.baseType(),
*_to.baseType(),
_encodeAsLibraryTypes,
- true
+ false
);
templ("encodeToMemoryFun", encodeToMemoryFun);
std::vector<std::map<std::string, std::string>> items(itemsPerSlot);
@@ -925,7 +925,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
FunctionType const& _from,
Type const& _to,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
)
{
solAssert(_from.kind() == FunctionType::Kind::External, "");
@@ -936,35 +936,31 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
_from.identifier() +
"_to_" +
_to.identifier() +
- (_compacted ? "_compacted" : "") +
+ (_fromStack ? "_fromStack" : "") +
(_encodeAsLibraryTypes ? "_library" : "");
- if (_compacted)
- {
+ if (_fromStack)
return createFunction(functionName, [&]() {
return Whiskers(R"(
- function <functionName>(addr_and_function_id, pos) {
- mstore(pos, <cleanExtFun>(addr_and_function_id))
+ function <functionName>(addr, function_id, pos) {
+ mstore(pos, <combineExtFun>(addr, function_id))
}
)")
("functionName", functionName)
- ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction())
+ ("combineExtFun", combineExternalFunctionIdFunction())
.render();
});
- }
else
- {
return createFunction(functionName, [&]() {
return Whiskers(R"(
- function <functionName>(addr, function_id, pos) {
- mstore(pos, <combineExtFun>(addr, function_id))
+ function <functionName>(addr_and_function_id, pos) {
+ mstore(pos, <cleanExtFun>(addr_and_function_id))
}
)")
("functionName", functionName)
- ("combineExtFun", combineExternalFunctionIdFunction())
+ ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction())
.render();
});
- }
}
string ABIFunctions::copyToMemoryFunction(bool _fromCalldata)
@@ -1212,10 +1208,7 @@ size_t ABIFunctions::headSize(TypePointers const& _targetTypes)
if (t->isDynamicallyEncoded())
headSize += 0x20;
else
- {
- solAssert(t->calldataEncodedSize() > 0, "");
headSize += t->calldataEncodedSize();
- }
}
return headSize;
diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h
index de2a140a..e61f68bc 100644
--- a/libsolidity/codegen/ABIFunctions.h
+++ b/libsolidity/codegen/ABIFunctions.h
@@ -89,13 +89,13 @@ private:
/// @returns the name of the ABI encoding function with the given type
/// and queues the generation of the function to the requested functions.
- /// @param _compacted if true, the input value was just loaded from storage
+ /// @param _fromStack if false, the input value was just loaded from storage
/// or memory and thus might be compacted into a single slot (depending on the type).
std::string abiEncodingFunction(
Type const& _givenType,
Type const& _targetType,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
);
/// Part of @a abiEncodingFunction for array target type and given calldata array.
std::string abiEncodingFunctionCalldataArray(
@@ -143,7 +143,7 @@ private:
FunctionType const& _from,
Type const& _to,
bool _encodeAsLibraryTypes,
- bool _compacted
+ bool _fromStack
);
/// @returns a function that copies raw bytes of dynamic length from calldata
diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp
index e17188c2..ce8cbb5f 100644
--- a/libsolidity/codegen/ArrayUtils.cpp
+++ b/libsolidity/codegen/ArrayUtils.cpp
@@ -291,8 +291,11 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
CompilerUtils utils(m_context);
unsigned baseSize = 1;
if (!_sourceType.isByteArray())
+ {
// We always pad the elements, regardless of _padToWordBoundaries.
baseSize = _sourceType.baseType()->calldataEncodedSize();
+ solAssert(baseSize >= 0x20, "");
+ }
if (_sourceType.location() == DataLocation::CallData)
{
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index d87c7be5..ce9c3b7f 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -38,6 +38,13 @@
#include <utility>
#include <numeric>
+// Change to "define" to output all intermediate code
+#undef SOL_OUTPUT_ASM
+#ifdef SOL_OUTPUT_ASM
+#include <libsolidity/inlineasm/AsmPrinter.h>
+#endif
+
+
using namespace std;
namespace dev
@@ -313,10 +320,17 @@ void CompilerContext::appendInlineAssembly(
ErrorReporter errorReporter(errors);
auto scanner = make_shared<Scanner>(CharStream(_assembly), "--CODEGEN--");
auto parserResult = assembly::Parser(errorReporter).parse(scanner);
- if (!parserResult || !errorReporter.errors().empty())
+#ifdef SOL_OUTPUT_ASM
+ cout << assembly::AsmPrinter()(*parserResult) << endl;
+#endif
+ assembly::AsmAnalysisInfo analysisInfo;
+ bool analyzerResult = false;
+ if (parserResult)
+ analyzerResult = assembly::AsmAnalyzer(analysisInfo, errorReporter, false, identifierAccess.resolve).analyze(*parserResult);
+ if (!parserResult || !errorReporter.errors().empty() || !analyzerResult)
{
string message =
- "Error parsing inline assembly block:\n"
+ "Error parsing/analyzing inline assembly block:\n"
"------------------ Input: -----------------\n" +
_assembly + "\n"
"------------------ Errors: ----------------\n";
@@ -331,9 +345,6 @@ void CompilerContext::appendInlineAssembly(
solAssert(false, message);
}
- assembly::AsmAnalysisInfo analysisInfo;
- assembly::AsmAnalyzer analyzer(analysisInfo, errorReporter, false, identifierAccess.resolve);
- solAssert(analyzer.analyze(*parserResult), "Failed to analyze inline assembly block.");
solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block.");
assembly::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system);
}
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index c2bf0f5c..bb8c4a94 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -858,8 +858,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE;
// Stack: memptr requested_length
// update free memory pointer
- m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize();
- m_context << Instruction::MUL << u256(32) << Instruction::ADD;
+ m_context << Instruction::DUP1;
+ // Stack: memptr requested_length requested_length
+ if (arrayType.isByteArray())
+ // Round up to multiple of 32
+ m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
+ else
+ m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL;
+ // stacK: memptr requested_length data_size
+ m_context << u256(32) << Instruction::ADD;
m_context << Instruction::DUP3 << Instruction::ADD;
utils().storeFreeMemoryPointer();
// Stack: memptr requested_length
@@ -1714,6 +1721,9 @@ void ExpressionCompiler::appendExternalFunctionCall(
if (_functionType.gasSet())
m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
+ else if (m_context.experimentalFeatureActive(ExperimentalFeature::V050))
+ // Send all gas (requires tangerine whistle EVM)
+ m_context << Instruction::GAS;
else
{
// send all gas except the amount needed to execute "SUB" and "CALL"