Repository: vyperlang/vyper

Issue:
Cannot add uint256s inside convert | Exception: Weird code element: l
### Version Information

* vyper Version (output of `vyper --version`): 0.2.16+commit.59e1bdd
* OS: Mac OS
* Python Version (output of `python --version`): Python 3.9.7

### What's your issue about?

When adding a number to a uint256 variable inside convert, Vyper refuses to compile the code and returns:
```
Error compiling: contracts/demoContract.vy
Exception: Weird code element: l
```

```Python
# @version 0.2.16
# demoContract.vy

@external
def badFunc():
    a : uint256 = 0
    b: Bytes[1] = slice(convert(a+1, bytes32), 32-1, 1)
```
It does not matter if the function is external or internal. 

The following code snippet does compile:
```Python
# @version 0.2.16

@external
def goodFunc():
    a : uint256 = 0
    c : bytes32 = convert(a+1, bytes32)
    b: Bytes[1] = slice(c, 32-1, 1)
```

<details>
  <summary>`vyper --debug demoContract.vy`</summary>

```
Traceback (most recent call last):
  File "PathToPython/bin/vyper", line 8, in <module>
    sys.exit(_parse_cli_args())
  File "PathToPython/lib/python3.9/site-packages/vyper/cli/vyper_compile.py", line 55, in _parse_cli_args
    return _parse_args(sys.argv[1:])
  File "PathToPython/lib/python3.9/site-packages/vyper/cli/vyper_compile.py", line 129, in _parse_args
    compiled = compile_files(
  File "PathToPython/lib/python3.9/site-packages/vyper/cli/vyper_compile.py", line 242, in compile_files
    compiler_data = vyper.compile_codes(
  File "PathToPython/lib/python3.9/site-packages/vyper/evm/opcodes.py", line 224, in _wrapper
    return fn(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/compiler/__init__.py", line 110, in compile_codes
    exc_handler(contract_name, exc)
  File "PathToPython/lib/python3.9/site-packages/vyper/cli/vyper_compile.py", line 166, in exc_handler
    raise exception
  File "PathToPython/lib/python3.9/site-packages/vyper/compiler/__init__.py", line 107, in compile_codes
    out[contract_name][output_format] = OUTPUT_FORMATS[output_format](compiler_data)
  File "PathToPython/lib/python3.9/site-packages/vyper/compiler/output.py", line 178, in build_bytecode_output
    return f"0x{compiler_data.bytecode.hex()}"
  File "PathToPython/lib/python3.9/site-packages/vyper/compiler/phases.py", line 146, in bytecode
    self._bytecode = generate_bytecode(self.assembly)
  File "PathToPython/lib/python3.9/site-packages/vyper/compiler/phases.py", line 134, in assembly
    self._assembly = generate_assembly(self.lll_nodes, self.use_ovm)
  File "PathToPython/lib/python3.9/site-packages/vyper/compiler/phases.py", line 277, in generate_assembly
    assembly = compile_lll.compile_to_assembly(lll_nodes)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 111, in compile_to_assembly
    res = _compile_to_assembly(code)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 307, in _compile_to_assembly
    o.extend(_compile_to_assembly(arg, withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 134, in _compile_to_assembly
    o.extend(_compile_to_assembly(c, withargs, existing_labels, break_dest, height + i))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 286, in _compile_to_assembly
    lll = _compile_to_assembly(code.args[0], {}, existing_labels, None, 0)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 307, in _compile_to_assembly
    o.extend(_compile_to_assembly(arg, withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 268, in _compile_to_assembly
    _compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height + 1,)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 307, in _compile_to_assembly
    o.extend(_compile_to_assembly(arg, withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 187, in _compile_to_assembly
    o.extend(_compile_to_assembly(code.args[1], withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 307, in _compile_to_assembly
    o.extend(_compile_to_assembly(arg, withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 264, in _compile_to_assembly
    o.extend(_compile_to_assembly(code.args[1], withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 268, in _compile_to_assembly
    _compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height + 1,)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 268, in _compile_to_assembly
    _compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height + 1,)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 268, in _compile_to_assembly
    _compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height + 1,)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 307, in _compile_to_assembly
    o.extend(_compile_to_assembly(arg, withargs, existing_labels, break_dest, height))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 268, in _compile_to_assembly
    _compile_to_assembly(code.args[2], withargs, existing_labels, break_dest, height + 1,)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 134, in _compile_to_assembly
    o.extend(_compile_to_assembly(c, withargs, existing_labels, break_dest, height + i))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 134, in _compile_to_assembly
    o.extend(_compile_to_assembly(c, withargs, existing_labels, break_dest, height + i))
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 99, in apply_line_no_wrapper
    ret = func(*args, **kwargs)
  File "PathToPython/lib/python3.9/site-packages/vyper/lll/compile_lll.py", line 518, in _compile_to_assembly
    raise Exception("Weird code element: " + repr(code))
Exception: Weird code element: l
```
</details>




Discussion:

Resolving patch:
diff --git a/vyper/builtin_functions/functions.py b/vyper/builtin_functions/functions.py
--- a/vyper/builtin_functions/functions.py
+++ b/vyper/builtin_functions/functions.py
@@ -304,7 +304,19 @@ def build_LLL(self, expr, args, kwargs, context):
             )
 
         if is_base_type(sub.typ, "bytes32"):
-            adj_sub = LLLnode.from_list(sub.args[0], typ=sub.typ, location="memory")
+            # optimize case when the expression is like (mload 352) or (sload 0)
+            if len(sub.args) == 1 and getattr(sub.args[0], "location", None) is not None:
+                adj_sub = sub.args[0]
+            else:
+                adj_sub = LLLnode.from_list(
+                    [
+                        "seq",
+                        ["mstore", MemoryPositions.FREE_VAR_SPACE, sub],
+                        MemoryPositions.FREE_VAR_SPACE,
+                    ],
+                    typ=sub.typ,
+                    location="memory",
+                )
 
         copier = make_byte_slice_copier(
             placeholder_plus_32_node,


Test patch:
diff --git a/tests/parser/functions/test_slice.py b/tests/parser/functions/test_slice.py
--- a/tests/parser/functions/test_slice.py
+++ b/tests/parser/functions/test_slice.py
@@ -100,6 +100,18 @@ def ret10_slice() -> Bytes[10]:
     c = get_contract(code)
     assert c.ret10_slice() == b"A"
 
+def test_slice_expr(get_contract):
+    # test slice of a complex expression
+    code = """
+@external
+def ret10_slice() -> Bytes[10]:
+    return slice(convert(65, bytes32), 31, 1)
+    """
+
+    c = get_contract(code)
+    assert c.ret10_slice() == b"A"
+
+
 
 code_bytes32 = [
     """
@@ -127,6 +139,16 @@ def bar() -> Bytes[32]:
     return slice(self.foo, a, b)
     """,
     """
+foo: Bytes[32]
+
+@external
+def bar() -> Bytes[32]:
+    self.foo = b"012\x03\x04\x05\x06\x0789abcdef0123456789abcdef"
+    a: uint256 = 3
+    b: uint256 = 5
+    return slice(convert(self.foo, bytes32), a, b)
+    """,
+    """
 @external
 def bar() -> Bytes[5]:
     foo: bytes32 = 0x0001020304050607080910111213141516171819202122232425262728293031