Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[llvm-context, solidity] Add CLI option '-g' to generate debug inform… #74

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
84ab968
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
8ea6bca
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
65aa72e
bump polkavm and polkadot-sdk (#87)
xermicus Oct 15, 2024
0166208
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
65b0042
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
ee1f273
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
1daa741
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
9596a02
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
dd86518
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
b4a9da8
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
cedd6bc
Makefile: remove duplicate workspace tests from the test target (#90)
xermicus Oct 17, 2024
2989e71
tidy up the runtime API crate (#85)
xermicus Oct 17, 2024
eaabae5
Implement extcodehash (#77)
ermalkaleci Oct 21, 2024
fbdac01
bump polkadot-sdk and polkavm (#94)
xermicus Oct 22, 2024
4d44d1a
standard json output: skip serializing keys instead of emitting a nul…
xermicus Oct 23, 2024
6eaa692
Set evm.deployedBytecode to the value of evm.bytecode (#95)
smiasojed Oct 24, 2024
fe6fdf0
support full storage key space (#100)
ermalkaleci Oct 28, 2024
083fb85
update polkadot-sdk and inkwell dependencies (#101)
xermicus Oct 29, 2024
c4db2d7
update LLVM target features (#102)
xermicus Oct 29, 2024
d78aded
support the origin opcode (#103)
xermicus Oct 29, 2024
eb8d102
update the polkadot-sdk and polkavm dependencies (#104)
xermicus Oct 30, 2024
677a440
display the git revision version information (#105)
xermicus Oct 30, 2024
c39a1e6
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
9a7ea91
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
11fd06b
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
b97e85a
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
84055ef
Merge branch 'main' into debug-info
Nov 4, 2024
1d4c3cb
[llvm-context, solidity] Add CLI option '-g' to generate debug inform…
Aug 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ log = { version = "0.4" }
# polkadot-sdk and friends
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.1", default-features = false }

polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "2b6b69641ccff4d7aa9c32051bbb2f1e775ef8cc" }

# llvm
Expand Down
1 change: 1 addition & 0 deletions crates/integration/contracts/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,4 @@ contract ERC20Tester {
assert(token.balanceOf(address(this)) == 0);
}
}

8 changes: 4 additions & 4 deletions crates/linker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ fn invoke_lld(cmd_args: &[&str]) -> bool {
unsafe { LLDELFLink(args.as_ptr(), args.len()) == 0 }
}

fn polkavm_linker<T: AsRef<[u8]>>(code: T) -> anyhow::Result<Vec<u8>> {
fn polkavm_linker<T: AsRef<[u8]>>(code: T, strip_binary: Option<bool>) -> anyhow::Result<Vec<u8>> {
let mut config = polkavm_linker::Config::default();
config.set_strip(true);
config.set_strip(strip_binary.unwrap_or(true));
config.set_optimize(true);

polkavm_linker::program_from_elf(config, code.as_ref())
.map_err(|reason| anyhow::anyhow!("polkavm linker failed: {}", reason))
}

pub fn link<T: AsRef<[u8]>>(input: T) -> anyhow::Result<Vec<u8>> {
pub fn link<T: AsRef<[u8]>>(input: T, strip_binary: Option<bool>) -> anyhow::Result<Vec<u8>> {
let dir = tempfile::tempdir().expect("failed to create temp directory for linking");
let output_path = dir.path().join("out.so");
let object_path = dir.path().join("out.o");
Expand Down Expand Up @@ -84,5 +84,5 @@ pub fn link<T: AsRef<[u8]>>(input: T) -> anyhow::Result<Vec<u8>> {
};

let blob = fs::read(&output_path)?;
polkavm_linker(blob)
polkavm_linker(blob, strip_binary)
}
1 change: 1 addition & 0 deletions crates/llvm-context/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub use self::polkavm::context::argument::Argument as PolkaVMArgument;
pub use self::polkavm::context::attribute::Attribute as PolkaVMAttribute;
pub use self::polkavm::context::build::Build as PolkaVMBuild;
pub use self::polkavm::context::code_type::CodeType as PolkaVMCodeType;
pub use self::polkavm::context::debug_info::DebugInfo;
pub use self::polkavm::context::evmla_data::EVMLAData as PolkaVMContextEVMLAData;
pub use self::polkavm::context::function::block::evmla_data::key::Key as PolkaVMFunctionBlockKey;
pub use self::polkavm::context::function::block::evmla_data::EVMLAData as PolkaVMFunctionBlockEVMLAData;
Expand Down
16 changes: 15 additions & 1 deletion crates/llvm-context/src/optimizer/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use itertools::Itertools;

use self::size_level::SizeLevel;

/// The LLVM optimizer settings.
/// The LLVM optimizer and code-gen settings.
#[derive(Debug, Serialize, Deserialize, Clone, Eq)]
pub struct Settings {
/// The middle-end optimization level.
Expand All @@ -26,6 +26,9 @@ pub struct Settings {
pub is_verify_each_enabled: bool,
/// Whether the LLVM `debug logging` option is enabled.
pub is_debug_logging_enabled: bool,

/// Whether to generate source-level debug information.
pub emit_debug_info: bool,
}

impl Settings {
Expand All @@ -44,6 +47,8 @@ impl Settings {

is_verify_each_enabled: false,
is_debug_logging_enabled: false,

emit_debug_info: false,
}
}

Expand All @@ -55,6 +60,8 @@ impl Settings {

is_verify_each_enabled: bool,
is_debug_logging_enabled: bool,

emit_debug_info: bool,
) -> Self {
Self {
level_middle_end,
Expand All @@ -65,6 +72,8 @@ impl Settings {

is_verify_each_enabled,
is_debug_logging_enabled,

emit_debug_info,
}
}

Expand Down Expand Up @@ -206,6 +215,11 @@ impl Settings {
pub fn is_fallback_to_size_enabled(&self) -> bool {
self.is_fallback_to_size_enabled
}

/// Whether source-level debug information should be emitted.
pub fn emit_debug_info(&self) -> bool {
self.emit_debug_info
}
}

impl PartialEq for Settings {
Expand Down
127 changes: 110 additions & 17 deletions crates/llvm-context/src/polkavm/context/debug_info.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,52 @@
//! The LLVM debug information.

use std::cell::RefCell;

use inkwell::debug_info::AsDIScope;
use num::Zero;
use inkwell::debug_info::DIScope;

/// Debug info scope stack
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ScopeStack<'ctx> {
stack: Vec<DIScope<'ctx>>,
}

// Abstract the type of the DIScope stack.
impl<'ctx> ScopeStack<'ctx> {
pub fn from(item: DIScope<'ctx>) -> Self {
Self { stack: vec![item] }
}

/// Return the top of the scope stack, or None if the stack is empty.
pub fn top(&self) -> Option<DIScope<'ctx>> {
self.stack.last().copied()
}

/// Push a scope onto the stack.
pub fn push(&mut self, scope: DIScope<'ctx>) {
self.stack.push(scope)
}

/// Pop the scope at the top of the stack and return it.
/// Return None if the stack is empty.
pub fn pop(&mut self) -> Option<DIScope<'ctx>> {
self.stack.pop()
}

/// Return the number of scopes on the stack.
pub fn len(&self) -> usize {
self.stack.len()
}
}

/// The LLVM debug information.
pub struct DebugInfo<'ctx> {
/// The compile unit.
compile_unit: inkwell::debug_info::DICompileUnit<'ctx>,
/// The debug info builder.
builder: inkwell::debug_info::DebugInfoBuilder<'ctx>,
/// Enclosing debug info scopes.
scope_stack: RefCell<ScopeStack<'ctx>>,
}

impl<'ctx> DebugInfo<'ctx> {
Expand All @@ -35,19 +73,43 @@ impl<'ctx> DebugInfo<'ctx> {
Self {
compile_unit,
builder,
scope_stack: RefCell::new(ScopeStack::from(compile_unit.as_debug_info_scope())),
}
}

/// Prepare an LLVM-IR module for debug-info generation
pub fn initialize_module(
&self,
llvm: &'ctx inkwell::context::Context,
module: &inkwell::module::Module<'ctx>,
) {
let debug_metadata_value = llvm
.i32_type()
.const_int(inkwell::debug_info::debug_metadata_version() as u64, false);
module.add_basic_value_flag(
"Debug Info Version",
inkwell::module::FlagBehavior::Warning,
debug_metadata_value,
);
self.push_scope(self.compilation_unit().get_file().as_debug_info_scope());
}

/// Finalize debug-info for an LLVM-IR module.
pub fn finalize_module(&self) {
self.builder().finalize()
}

/// Creates a function info.
pub fn create_function(
&self,
name: &str,
) -> anyhow::Result<inkwell::debug_info::DISubprogram<'ctx>> {
let flags = inkwell::debug_info::DIFlagsConstants::ZERO;
let subroutine_type = self.builder.create_subroutine_type(
self.compile_unit.get_file(),
Some(self.create_type(revive_common::BIT_LENGTH_FIELD)?),
Some(self.create_word_type(Some(flags))?.as_type()),
&[],
inkwell::debug_info::DIFlags::zero(),
flags,
);

let function = self.builder.create_function(
Expand All @@ -60,7 +122,7 @@ impl<'ctx> DebugInfo<'ctx> {
true,
false,
1,
inkwell::debug_info::DIFlags::zero(),
flags,
false,
);

Expand All @@ -74,24 +136,55 @@ impl<'ctx> DebugInfo<'ctx> {
Ok(function)
}

/// Creates a primitive type info.
pub fn create_type(
/// Creates primitive integer type debug-info.
pub fn create_primitive_type(
&self,
bit_length: usize,
) -> anyhow::Result<inkwell::debug_info::DIType<'ctx>> {
flags: Option<inkwell::debug_info::DIFlags>,
) -> anyhow::Result<inkwell::debug_info::DIBasicType<'ctx>> {
let di_flags = flags.unwrap_or(inkwell::debug_info::DIFlagsConstants::ZERO);
let di_encoding: u32 = 0;
let type_name = String::from("U") + bit_length.to_string().as_str();
self.builder
.create_basic_type(
"U256",
bit_length as u64,
0,
inkwell::debug_info::DIFlags::zero(),
)
.map(|basic_type| basic_type.as_type())
.create_basic_type(type_name.as_str(), bit_length as u64, di_encoding, di_flags)
.map_err(|error| anyhow::anyhow!("Debug info error: {}", error))
}

/// Finalizes the builder.
pub fn finalize(&self) {
self.builder.finalize();
/// Returns the debug-info model of word-sized integer types.
pub fn create_word_type(
&self,
flags: Option<inkwell::debug_info::DIFlags>,
) -> anyhow::Result<inkwell::debug_info::DIBasicType<'ctx>> {
self.create_primitive_type(revive_common::BIT_LENGTH_WORD, flags)
}

/// Return the DIBuilder.
pub fn builder(&self) -> &inkwell::debug_info::DebugInfoBuilder<'ctx> {
&self.builder
}

/// Return the compilation unit. {
pub fn compilation_unit(&self) -> &inkwell::debug_info::DICompileUnit<'ctx> {
&self.compile_unit
}

/// Push a debug-info scope onto the stack.
pub fn push_scope(&self, scope: DIScope<'ctx>) {
self.scope_stack.borrow_mut().push(scope)
}

/// Pop the top of the debug-info scope stack and return it.
pub fn pop_scope(&self) -> Option<DIScope<'ctx>> {
self.scope_stack.borrow_mut().pop()
}

/// Return the top of the debug-info scope stack.
pub fn top_scope(&self) -> Option<DIScope<'ctx>> {
self.scope_stack.borrow().top()
}

/// Return the number of debug-info scopes on the scope stack.
pub fn num_scopes(&self) -> usize {
self.scope_stack.borrow().len()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ impl<'ctx> Declaration<'ctx> {
) -> Self {
Self { r#type, value }
}

pub fn function_value(&self) -> inkwell::values::FunctionValue<'ctx> {
self.value
}
}
10 changes: 10 additions & 0 deletions crates/llvm-context/src/polkavm/context/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub mod yul_data;

use std::collections::HashMap;

use inkwell::debug_info::AsDIScope;

use crate::optimizer::settings::size_level::SizeLevel;
use crate::optimizer::Optimizer;
use crate::polkavm::context::attribute::Attribute;
Expand Down Expand Up @@ -94,6 +96,14 @@ impl<'ctx> Function<'ctx> {
self.declaration
}

/// Returns the debug-info scope.
pub fn get_debug_scope(&self) -> Option<inkwell::debug_info::DIScope<'ctx>> {
self.declaration()
.function_value()
.get_subprogram()
.map(|scp| scp.as_debug_info_scope())
}

/// Returns the N-th parameter of the function.
pub fn get_nth_param(&self, index: usize) -> inkwell::values::BasicValueEnum<'ctx> {
self.declaration()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ where
}

fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
context.set_current_function(runtime::FUNCTION_DEPLOY_CODE)?;
context.set_current_function(runtime::FUNCTION_DEPLOY_CODE, None)?;

context.set_basic_block(context.current_function().borrow().entry_block());
context.set_code_type(CodeType::Deploy);

self.inner.into_llvm(context)?;
context.set_debug_location(0, 0, None)?;

match context
.basic_block()
.get_last_instruction()
Expand All @@ -72,8 +74,11 @@ where
}

context.set_basic_block(context.current_function().borrow().return_block());
context.set_debug_location(0, 0, None)?;
context.build_return(None);

context.pop_debug_scope();

Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ impl Entry {
where
D: Dependency + Clone,
{
context.set_debug_location(0, 0, None)?;

let is_deploy = context
.current_function()
.borrow()
Expand Down Expand Up @@ -214,7 +216,7 @@ where
true,
);

context.set_current_function(runtime::FUNCTION_ENTRY)?;
context.set_current_function(runtime::FUNCTION_ENTRY, None)?;
context.set_basic_block(context.current_function().borrow().entry_block());

Self::initialize_globals(context)?;
Expand All @@ -225,6 +227,8 @@ where
context.set_basic_block(context.current_function().borrow().return_block());
context.build_unreachable();

context.pop_debug_scope();

Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ where
}

fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
context.set_current_function(runtime::FUNCTION_LOAD_IMMUTABLE_DATA)?;
context.set_current_function(runtime::FUNCTION_LOAD_IMMUTABLE_DATA, None)?;
context.set_basic_block(context.current_function().borrow().entry_block());

let immutable_data_size_pointer = context
Expand Down Expand Up @@ -111,6 +111,8 @@ where
context.set_basic_block(return_block);
context.build_return(None);

context.pop_debug_scope();

Ok(())
}
}
Loading