| 1561 | } |
| 1562 | |
| 1563 | unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWords) |
| 1564 | { |
| 1565 | solAssert(_type.isValueType()); |
| 1566 | Type const* type = &_type; |
| 1567 | if (auto const* userDefined = dynamic_cast<UserDefinedValueType const*>(type)) |
| 1568 | type = &userDefined->underlyingType(); |
| 1569 | |
| 1570 | unsigned numBytes = type->calldataEncodedSize(_padToWords); |
| 1571 | bool isExternalFunctionType = false; |
| 1572 | if (auto const* funType = dynamic_cast<FunctionType const*>(type)) |
| 1573 | if (funType->kind() == FunctionType::Kind::External) |
| 1574 | isExternalFunctionType = true; |
| 1575 | if (numBytes == 0) |
| 1576 | { |
| 1577 | m_context << Instruction::POP << u256(0); |
| 1578 | return numBytes; |
| 1579 | } |
| 1580 | solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested."); |
| 1581 | m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD); |
| 1582 | bool cleanupNeeded = true; |
| 1583 | if (isExternalFunctionType) |
| 1584 | splitExternalFunctionType(true); |
| 1585 | else if (numBytes != 32) |
| 1586 | { |
| 1587 | // add leading or trailing zeros by dividing/multiplying depending on alignment |
| 1588 | unsigned shiftFactor = (32 - numBytes) * 8; |
| 1589 | rightShiftNumberOnStack(shiftFactor); |
| 1590 | if (type->leftAligned()) |
| 1591 | { |
| 1592 | leftShiftNumberOnStack(shiftFactor); |
| 1593 | cleanupNeeded = false; |
| 1594 | } |
| 1595 | else if (IntegerType const* intType = dynamic_cast<IntegerType const*>(type)) |
| 1596 | if (!intType->isSigned()) |
| 1597 | cleanupNeeded = false; |
| 1598 | } |
| 1599 | if (_fromCalldata) |
| 1600 | convertType(_type, *type, cleanupNeeded, false, true); |
| 1601 | |
| 1602 | return numBytes; |
| 1603 | } |
| 1604 | |
| 1605 | void CompilerUtils::cleanHigherOrderBits(IntegerType const& _typeOnStack) |
| 1606 | { |
nothing calls this directly
no test coverage detected