experimental: support for debug info (#118)

Signed-off-by: wpt967 <matt.aw@parity.io>
Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
Cyrill Leutwiler authored and GitHub committed 2024-11-22 08:56:09 +01:00
1 parent 87f2bcefb3
commit dbb47fd13e
44 files changed
+730 -285

No files matched your search

+15 -5
View File
@@ -21,7 +21,7 @@ pub struct Lexer {
/// The input source code.
input: String,
/// The number of characters processed so far.
offset: usize,
offset: u32,
/// The current location.
location: Location,
/// The peeked lexeme, waiting to be fetched.
@@ -48,8 +48,17 @@ impl Lexer {
return Ok(peeked);
}
while self.offset < self.input.len() {
let input = &self.input[self.offset..];
while self.offset
< self
.input
.len()
.try_into()
.map_err(|_| Error::InvalidLexeme {
location: self.location,
sequence: Default::default(),
})?
{
let input = &self.input[(self.offset as usize)..];
if input.starts_with(|character| char::is_ascii_whitespace(&character)) {
if input.starts_with('\n') {
@@ -101,12 +110,13 @@ impl Lexer {
return Ok(token);
}
let end = self.input[self.offset..]
let end = self.input[(self.offset as usize)..]
.find(char::is_whitespace)
.unwrap_or(self.input.len());
return Err(Error::InvalidLexeme {
location: self.location,
sequence: self.input[self.offset..self.offset + end].to_owned(),
sequence: self.input[(self.offset as usize)..(self.offset as usize) + end]
.to_owned(),
});
}
@@ -19,12 +19,20 @@ impl Comment {
let end_position = input.find(Self::END).unwrap_or(input.len());
let input = &input[..end_position];
let length = end_position + Self::END.len();
let lines = input.matches('\n').count();
let length = (end_position + Self::END.len())
.try_into()
.expect("the YUL should be of reasonable size");
let lines = input
.matches('\n')
.count()
.try_into()
.expect("the YUL should be of reasonable size");
let columns = match input.rfind('\n') {
Some(new_line) => end_position - (new_line + 1),
None => end_position,
};
}
.try_into()
.expect("the YUL should be of reasonable size");
Token::new(Location::new(lines, columns), Lexeme::Comment, length)
}
@@ -17,7 +17,9 @@ impl Comment {
/// Returns the comment's length, including the trimmed whitespace around it.
pub fn parse(input: &str) -> Token {
let end_position = input.find(Self::END).unwrap_or(input.len());
let length = end_position + Self::END.len();
let length = (end_position + Self::END.len())
.try_into()
.expect("the YUL should be of reasonable size");
Token::new(Location::new(1, 1), Lexeme::Comment, length)
}
@@ -26,7 +26,10 @@ impl Identifier {
let end = input.find(Self::cannot_continue).unwrap_or(input.len());
let inner = input[..end].to_string();
let length = inner.len();
let length = inner
.len()
.try_into()
.expect("the YUL should be of reasonable size");
if let Some(token) = Keyword::parse(inner.as_str()) {
return Some(token);
@@ -58,6 +58,9 @@ impl Keyword {
if length != input.len() {
return None;
}
let length = length
.try_into()
.expect("the YUL should be of reasonable size");
Some(Token::new(Location::new(0, length), lexeme, length))
}
@@ -54,6 +54,10 @@ impl Integer {
return None;
};
let length = length
.try_into()
.expect("the YUL should be of reasonable size");
let token = Token::new(
Location::new(0, length),
Lexeme::Literal(Literal::Integer(value)),
@@ -69,6 +69,9 @@ impl String {
.to_owned();
let literal = Self::new(string, is_hex_string);
let length = length
.try_into()
.expect("the YUL should be of reasonable size");
Some(Token::new(
Location::new(0, length),
@@ -7,9 +7,9 @@ use serde::Serialize;
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Eq)]
pub struct Location {
/// The line number, starting from 1.
pub line: usize,
pub line: u32,
/// The column number, starting from 1.
pub column: usize,
pub column: u32,
}
impl Default for Location {
@@ -20,13 +20,13 @@ impl Default for Location {
impl Location {
/// Creates a default location.
pub fn new(line: usize, column: usize) -> Self {
pub fn new(line: u32, column: u32) -> Self {
Self { line, column }
}
/// Mutates the location by shifting the original one down by `lines` and
/// setting the column to `column`.
pub fn shift_down(&mut self, lines: usize, column: usize) {
pub fn shift_down(&mut self, lines: u32, column: u32) {
if lines == 0 {
self.shift_right(column);
return;
@@ -37,7 +37,7 @@ impl Location {
}
/// Mutates the location by shifting the original one rightward by `columns`.
pub fn shift_right(&mut self, columns: usize) {
pub fn shift_right(&mut self, columns: u32) {
self.column += columns;
}
}
+2 -2
View File
@@ -15,12 +15,12 @@ pub struct Token {
/// The lexeme.
pub lexeme: Lexeme,
/// The token length, including whitespaces.
pub length: usize,
pub length: u32,
}
impl Token {
/// A shortcut constructor.
pub fn new(location: Location, lexeme: Lexeme, length: usize) -> Self {
pub fn new(location: Location, lexeme: Lexeme, length: u32) -> Self {
Self {
location,
lexeme,
+3
View File
@@ -57,4 +57,7 @@ pub enum Error {
/// The list of invalid attributes.
values: BTreeSet<String>,
},
/// Invalid code length.
#[error("The line or column length exceed the maximum of u32::MAX")]
InvalidLength,
}
@@ -47,7 +47,11 @@ impl Assignment {
.into());
}
};
let length = identifier.inner.len();
let length = identifier
.inner
.len()
.try_into()
.map_err(|_| Error::Parser(ParserError::InvalidLength))?;
match lexer.peek()? {
Token {
@@ -115,6 +119,8 @@ where
mut self,
context: &mut revive_llvm_context::PolkaVMContext<D>,
) -> anyhow::Result<()> {
context.set_debug_location(self.location.line, 0, None)?;
let value = match self.initializer.into_llvm(context)? {
Some(value) => value,
None => return Ok(()),
@@ -142,6 +148,8 @@ where
context.build_store(tuple_pointer, value.to_llvm())?;
for (index, binding) in self.bindings.into_iter().enumerate() {
context.set_debug_location(self.location.line, 0, None)?;
let field_pointer = context.build_gep(
tuple_pointer,
&[
@@ -5,6 +5,8 @@ use std::collections::HashSet;
use serde::Deserialize;
use serde::Serialize;
use inkwell::debug_info::AsDIScope;
use crate::yul::error::Error;
use crate::yul::lexer::token::lexeme::symbol::Symbol;
use crate::yul::lexer::token::lexeme::Lexeme;
@@ -153,9 +155,26 @@ where
function.into_llvm(context)?;
}
context.set_current_function(current_function.as_str())?;
context.set_current_function(current_function.as_str(), Some(self.location.line))?;
if let Some(debug_info) = context.debug_info() {
let di_builder = debug_info.builder();
let di_scope = debug_info.top_scope().expect("expected a debug-info scope");
let di_block_scope = di_builder
.create_lexical_block(
di_scope,
debug_info.compilation_unit().get_file(),
self.location.line,
0,
)
.as_debug_info_scope();
context.push_debug_scope(di_block_scope);
context.set_debug_location(self.location.line, 0, None)?;
}
context.set_basic_block(current_block);
for statement in local_statements.into_iter() {
context.set_debug_location(statement.location().line, 0, None)?;
if context.basic_block().get_terminator().is_some() {
break;
}
@@ -194,6 +213,8 @@ where
}
}
context.pop_debug_scope();
Ok(())
}
}
@@ -55,7 +55,11 @@ impl Expression {
.into());
}
};
let length = identifier.inner.len();
let length = identifier
.inner
.len()
.try_into()
.map_err(|_| Error::Parser(ParserError::InvalidLength))?;
match lexer.peek()? {
Token {
@@ -4,6 +4,7 @@ use std::collections::BTreeSet;
use std::collections::HashSet;
use inkwell::types::BasicType;
use serde::Deserialize;
use serde::Serialize;
@@ -229,14 +230,15 @@ where
mut self,
context: &mut revive_llvm_context::PolkaVMContext<D>,
) -> anyhow::Result<()> {
context.set_current_function(self.identifier.as_str())?;
let r#return = context.current_function().borrow().r#return();
context.set_current_function(self.identifier.as_str(), Some(self.location.line))?;
context.set_basic_block(context.current_function().borrow().entry_block());
let r#return = context.current_function().borrow().r#return();
match r#return {
revive_llvm_context::PolkaVMFunctionReturn::None => {}
revive_llvm_context::PolkaVMFunctionReturn::Primitive { pointer } => {
let identifier = self.result.pop().expect("Always exists");
let r#type = identifier.r#type.unwrap_or_default();
context.build_store(pointer, r#type.into_llvm(context).const_zero())?;
context
@@ -288,6 +290,8 @@ where
}
self.body.into_llvm(context)?;
context.set_debug_location(self.location.line, 0, None)?;
match context
.basic_block()
.get_last_instruction()
@@ -314,6 +318,8 @@ where
}
}
context.pop_debug_scope();
Ok(())
}
}
@@ -2,6 +2,8 @@
use std::collections::HashSet;
use inkwell::debug_info::AsDIScope;
use serde::Deserialize;
use serde::Serialize;
@@ -217,16 +219,30 @@ where
}
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
if let Some(debug_info) = context.debug_info() {
let di_builder = debug_info.builder();
let object_name: &str = self.identifier.as_str();
let di_parent_scope = debug_info
.top_scope()
.expect("expected an existing debug-info scope");
let object_scope = di_builder.create_namespace(di_parent_scope, object_name, true);
context.push_debug_scope(object_scope.as_debug_info_scope());
}
if self.identifier.ends_with("_deployed") {
revive_llvm_context::PolkaVMImmutableDataLoadFunction.into_llvm(context)?;
revive_llvm_context::PolkaVMRuntimeCodeFunction::new(self.code).into_llvm(context)?;
} else {
revive_llvm_context::PolkaVMDeployCodeFunction::new(self.code).into_llvm(context)?;
}
context.set_debug_location(self.location.line, 0, None)?;
if let Some(object) = self.inner_object {
object.into_llvm(context)?;
}
context.set_debug_location(self.location.line, 0, None)?;
context.pop_debug_scope();
Ok(())
}
@@ -101,7 +101,9 @@ where
) -> anyhow::Result<()> {
if self.bindings.len() == 1 {
let identifier = self.bindings.remove(0);
let r#type = identifier.r#type.unwrap_or_default().into_llvm(context);
context.set_debug_location(self.location.line, 0, None)?;
let identifier_type = identifier.r#type.clone().unwrap_or_default();
let r#type = identifier_type.into_llvm(context);
let pointer = context.build_alloca(r#type, identifier.inner.as_str());
context
.current_function()
@@ -116,7 +118,7 @@ where
.current_function()
.borrow_mut()
.yul_mut()
.insert_constant(identifier.inner, constant);
.insert_constant(identifier.inner.clone(), constant);
}
value.to_llvm()
@@ -131,6 +133,8 @@ where
}
for (index, binding) in self.bindings.iter().enumerate() {
context.set_debug_location(self.location.line, 0, None)?;
let yul_type = binding
.r#type
.to_owned()