diff --git a/vyper/cli/vyper_compile.py b/vyper/cli/vyper_compile.py index d390e3bb8a..cdcb498de3 100755 --- a/vyper/cli/vyper_compile.py +++ b/vyper/cli/vyper_compile.py @@ -22,7 +22,8 @@ blueprint_bytecode - Deployment bytecode for an ERC-5202 compatible blueprint abi - ABI in JSON format abi_python - ABI in python format -source_map - Vyper source map +source_map - Vyper source map of deployable bytecode +source_map_runtime - Vyper source map of runtime bytecode method_identifiers - Dictionary of method signature to method identifier userdoc - Natspec user documentation devdoc - Natspec developer documentation @@ -48,6 +49,7 @@ "abi", "layout", "source_map", + "source_map_runtime", "method_identifiers", "userdoc", "devdoc", diff --git a/vyper/cli/vyper_json.py b/vyper/cli/vyper_json.py index 71b0c6a1b3..0e5a4bd21f 100755 --- a/vyper/cli/vyper_json.py +++ b/vyper/cli/vyper_json.py @@ -22,10 +22,12 @@ "evm.methodIdentifiers": "method_identifiers", "evm.bytecode.object": "bytecode", "evm.bytecode.opcodes": "opcodes", + "evm.bytecode.sourceMap": "source_map", + "evm.bytecode.sourceMapFull": "source_map_full", "evm.deployedBytecode.object": "bytecode_runtime", "evm.deployedBytecode.opcodes": "opcodes_runtime", - "evm.deployedBytecode.sourceMap": "source_map", - "evm.deployedBytecode.sourceMapFull": "source_map_full", + "evm.deployedBytecode.sourceMap": "source_map_runtime", + "evm.deployedBytecode.sourceMapFull": "source_map_full_runtime", "interface": "interface", "ir": "ir_dict", "ir_runtime": "ir_runtime_dict", @@ -341,24 +343,28 @@ def format_to_output_dict(compiler_data: dict) -> dict: output_contracts["evm"] = {"methodIdentifiers": data["method_identifiers"]} evm_keys = ("bytecode", "opcodes") - if any(i in data for i in evm_keys): + pc_maps_keys = ("source_map", "source_map_full") + if any(i in data for i in evm_keys) or any(i in data for i in pc_maps_keys): evm = output_contracts.setdefault("evm", {}).setdefault("bytecode", {}) if "bytecode" in data: evm["object"] = data["bytecode"] if "opcodes" in data: evm["opcodes"] = data["opcodes"] + if "source_map" in data: + evm["sourceMap"] = data["source_map"]["pc_pos_map_compressed"] + if "source_map_full" in data: + evm["sourceMapFull"] = data["source_map_full"] - pc_maps_keys = ("source_map", "source_map_full") - if any(i + "_runtime" in data for i in evm_keys) or any(i in data for i in pc_maps_keys): + if any(i + "_runtime" in data for i in evm_keys): evm = output_contracts.setdefault("evm", {}).setdefault("deployedBytecode", {}) if "bytecode_runtime" in data: evm["object"] = data["bytecode_runtime"] if "opcodes_runtime" in data: evm["opcodes"] = data["opcodes_runtime"] - if "source_map" in data: - evm["sourceMap"] = data["source_map"]["pc_pos_map_compressed"] - if "source_map_full" in data: - evm["sourceMapFull"] = data["source_map_full"] + if "source_map_runtime" in data: + evm["sourceMap"] = data["source_map_runtime"]["pc_pos_map_compressed"] + if "source_map_full_runtime" in data: + evm["sourceMapFull"] = data["source_map_full_runtime"] return output_dict diff --git a/vyper/compiler/__init__.py b/vyper/compiler/__init__.py index 47e2054bd8..328a16c3b2 100644 --- a/vyper/compiler/__init__.py +++ b/vyper/compiler/__init__.py @@ -35,6 +35,8 @@ "asm": output.build_asm_output, "source_map": output.build_source_map_output, "source_map_full": output.build_source_map_output, + "source_map_runtime": output.build_source_map_runtime_output, + "source_map_full_runtime": output.build_source_map_runtime_output, # requires bytecode "bytecode": output.build_bytecode_output, "bytecode_runtime": output.build_bytecode_runtime_output, diff --git a/vyper/compiler/output.py b/vyper/compiler/output.py index 9b3bd147ef..76f720f863 100644 --- a/vyper/compiler/output.py +++ b/vyper/compiler/output.py @@ -246,16 +246,13 @@ def _build_node_identifier(ast_node): return (ast_node.module_node.source_id, ast_node.node_id) -def build_source_map_output(compiler_data: CompilerData) -> dict: +def _build_source_map_output(compiler_data, bytecode, pc_maps): """ Generate source map output in various formats. Note that integrations are encouraged to use pc_ast_map since the information it provides is a superset of the other formats, and the other types are included for legacy reasons. """ - bytecode, pc_maps = compile_ir.assembly_to_evm( - compiler_data.assembly_runtime, insert_compiler_metadata=False - ) # sort the pc maps alphabetically # CMC 2024-03-09 is this really necessary? out = {} @@ -280,6 +277,20 @@ def build_source_map_output(compiler_data: CompilerData) -> dict: return out +def build_source_map_output(compiler_data: CompilerData) -> dict: + bytecode, pc_maps = compile_ir.assembly_to_evm( + compiler_data.assembly, insert_compiler_metadata=False + ) + return _build_source_map_output(compiler_data, bytecode, pc_maps) + + +def build_source_map_runtime_output(compiler_data: CompilerData) -> dict: + bytecode, pc_maps = compile_ir.assembly_to_evm( + compiler_data.assembly_runtime, insert_compiler_metadata=False + ) + return _build_source_map_output(compiler_data, bytecode, pc_maps) + + # generate a solidity-style source map. this functionality is deprecated # in favor of pc_ast_map, and may not be maintained to the same level # as pc_ast_map.