Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.

Commit

Permalink
Dwarf instructions (#409)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcivlin authored Jan 17, 2024
1 parent d76a742 commit 1d1e920
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 7 deletions.
139 changes: 137 additions & 2 deletions language/solana/move-to-solana/src/stackless/dwarf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
//! - Hides weirdly mutable array pointers.
//! - Provides high-level instruction builders compatible with the stackless bytecode model.
use crate::stackless::{extensions::FunctionEnvExt, FunctionContext, Module, TargetData};
use crate::stackless::{extensions::FunctionEnvExt, llvm::Module, FunctionContext, TargetData};
use anyhow::{Context, Result};
use codespan::Location;
use itertools::enumerate;
use llvm_sys::{
Expand All @@ -35,12 +36,15 @@ use llvm_sys::{
};

use log::{debug, error, warn};
use move_model::model::{ModuleId, StructId};
use move_model::model::{GlobalEnv, ModuleId, StructId};
use move_stackless_bytecode::stackless_bytecode::Bytecode;
use std::{
cell::RefCell,
collections::{HashMap, HashSet},
env,
ffi::CStr,
fs::File,
io::{BufRead, BufReader, Read, Seek, SeekFrom},
ptr,
};

Expand Down Expand Up @@ -97,6 +101,43 @@ pub enum UnresolvedPrintLogLevel {
Error,
}

pub struct Instruction<'up> {
bc: &'up Bytecode,
func_ctx: &'up FunctionContext<'up, 'up>,
loc: move_model::model::Loc,
}

impl<'up> Instruction<'up> {
fn new(bc: &'up Bytecode, func_ctx: &'up FunctionContext<'_, '_>) -> Instruction<'up> {
let loc = func_ctx
.env
.get_bytecode_loc(bc.get_attr_id().as_usize() as u16);
Instruction { bc, func_ctx, loc }
}
fn debug(&self) {
let bc = self.bc;
let loc = &self.loc;
let (file, _line, _column, start, end) = self.loc_display();

let (start_line, start_column) = find_line_column(&file, start as usize).unwrap_or((-1, 0));
let (end_line, end_column) = find_line_column(&file, end as usize).unwrap_or((-1, 0));
debug!(target: "bytecode", "{:#?} loc {:#?}", bc, loc);
let substring = read_substring(&file, start as usize, end as usize)
.unwrap_or("String not found".to_string());
debug!(target: "bytecode", "file {:#?}[{start}-{end}]:{start_line}.{start_column}-{end_line}.{end_column} {substring}", file);
}
fn loc_display(&self) -> (String, u32, u32, u32, u32) {
let g_env = self.func_ctx.module_cx.env.env;
let loc = &self.loc;
loc_display(loc, g_env)
}
fn create_load_store(&self, _load: *mut LLVMValue, _store: *mut LLVMValue, mty: &mty::Type) {
let bc = self.bc;
let loc = &self.loc;
debug!(target: "bytecode", "create_load_store {:#?} loc {:#?} mty {:#?}", bc, loc, mty);
}
}

pub fn type_get_name(x: LLVMMetadataRef) -> String {
let mut length: ::libc::size_t = 0;
let name_c_str = unsafe { LLVMDITypeGetName(x, &mut length) };
Expand Down Expand Up @@ -722,6 +763,11 @@ impl<'up> DIBuilder<'up> {
)
};

let llvm_builder = &mod_cx.llvm_builder;

let entry_bb = llvm_builder.get_entry_basic_block(ll_fn);
dbg!(entry_bb);

let module_di = &self.module_di().unwrap();
let module_ctx = unsafe { LLVMGetModuleContext(*module_di) };
let meta_as_value = unsafe { LLVMMetadataAsValue(module_ctx, function) };
Expand Down Expand Up @@ -967,9 +1013,98 @@ impl<'up> DIBuilder<'up> {
}
}

pub fn create_instruction<'a>(
&self,
bc: &'a Bytecode,
func_ctx: &'a FunctionContext<'_, '_>,
) -> Option<Instruction<'a>> {
if let Some(_di_builder_core) = &self.0 {
let instr = Instruction::new(bc, func_ctx);
instr.debug();
return Some(instr);
}
None
}

pub fn create_load_store(
&self,
instr: Option<Instruction>,
load: *mut LLVMValue,
store: *mut LLVMValue,
mty: &mty::Type,
) {
if let Some(_di_builder_core) = &self.0 {
if let Some(instruction) = instr {
instruction.create_load_store(load, store, mty);
}
}
}

pub fn finalize(&self) {
if let Some(x) = &self.0 {
unsafe { LLVMDIBuilderFinalize(x.builder_ref) };
}
}
}

fn loc_display(loc: &move_model::model::Loc, env: &GlobalEnv) -> (String, u32, u32, u32, u32) {
if let Some((fname, pos)) = env.get_file_and_location(loc) {
(
fname,
(pos.line + codespan::LineOffset(1)).0,
(pos.column + codespan::ColumnOffset(1)).0,
loc.span().start().0,
loc.span().end().0,
)
} else {
("unknown source".to_string(), 0, 0, 0, 0)
}
}

fn find_line_column(file_path: &str, find_offset: usize) -> Result<(i32, usize)> {
// Open the file
let file = File::open(file_path)?;
let reader = BufReader::new(file);

// Read the file line by line
let mut current_offset = 0;
let mut line_number = 1;

for line in reader.lines() {
let line = line?;
let line_length = line.len() + 1; // Add 1 for the newline character

if current_offset + line_length > find_offset {
// Found the line where the substring starts
let start_column = find_offset - current_offset;
debug!(target: "bytecode", "{:#?} offset {find_offset} @ {line_number}:{start_column}", file_path);
return Ok((line_number, start_column));
}

// Move to the next line
current_offset += line_length;
line_number += 1;
}

// Substring spans multiple lines. Unable to determine end position.
let err_msg = "Substring spans multiple lines. Unable to determine end position.";
Err(anyhow::anyhow!(err_msg)).with_context(|| format!("Error processing file: {}", file_path))
}

// for debugging: for a given ascii file returns substring in the range file[begin, end]
fn read_substring(file_path: &str, begin: usize, end: usize) -> anyhow::Result<String> {
// Open the file
let mut file = File::open(file_path)?;

// Seek to the beginning of the substring
file.seek(SeekFrom::Start(begin as u64))?;

// Read the substring into a buffer
let mut buffer = Vec::with_capacity(end - begin);
file.take((end - begin) as u64).read_to_end(&mut buffer)?;

// Convert the buffer to a String
let substring = String::from_utf8(buffer)?;

Ok(substring)
}
13 changes: 11 additions & 2 deletions language/solana/move-to-solana/src/stackless/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,10 +527,16 @@ impl Builder {
}

/// Load an alloca and store in another.
pub fn load_store(&self, ty: Type, src: Alloca, dst: Alloca) {
pub fn load_store(
&self,
ty: Type,
src: Alloca,
dst: Alloca,
) -> (*mut LLVMValue, *mut LLVMValue) {
unsafe {
let tmp_reg = LLVMBuildLoad2(self.0, ty.0, src.0, "load_store_tmp".cstr());
LLVMBuildStore(self.0, tmp_reg, dst.0);
let store = LLVMBuildStore(self.0, tmp_reg, dst.0);
(tmp_reg, store)
}
}

Expand Down Expand Up @@ -1227,6 +1233,9 @@ impl BasicBlock {
pub fn get_basic_block_parent(&self) -> Function {
unsafe { Function(LLVMGetBasicBlockParent(self.0)) }
}
pub fn get_basic_block_ref(&self) -> &LLVMBasicBlockRef {
&self.0
}
}

#[derive(Copy, Clone, Debug)]
Expand Down
18 changes: 15 additions & 3 deletions language/solana/move-to-solana/src/stackless/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ use codespan::Location;
use llvm_sys::core::LLVMGetModuleContext;
use log::debug;
use move_core_types::{account_address, u256::U256, vm_status::StatusCode::ARITHMETIC_ERROR};
use move_model::{ast as mast, model as mm, ty as mty};
use move_model::{
ast as mast,
model::{self as mm},
ty as mty,
};
use move_stackless_bytecode::{
function_target::FunctionData, stackless_bytecode as sbc,
stackless_bytecode_generator::StacklessBytecodeGenerator,
Expand Down Expand Up @@ -221,7 +225,10 @@ impl<'mm, 'up> FunctionContext<'mm, 'up> {
let map_node_to_type: BTreeMap<mm::NodeId, move_model::ty::Type> = g_env
.get_nodes()
.iter()
.map(|nd| (*nd, g_env.get_node_type(*nd)))
.map(|nd| {
debug!(target: "nodes", "{:#?} {:#?}", nd, g_env.get_node_loc(*nd));
(*nd, g_env.get_node_type(*nd))
})
.collect();
debug!(target: "nodes", "\n{:#?}", &map_node_to_type);

Expand Down Expand Up @@ -354,12 +361,16 @@ impl<'mm, 'up> FunctionContext<'mm, 'up> {

fn translate_instruction(&mut self, instr: &sbc::Bytecode) {
let builder = &self.module_cx.llvm_builder;
let builder_di = &self.module_cx.llvm_di_builder;
let instr_dbg = builder_di.create_instruction(instr, self);

match instr {
sbc::Bytecode::Assign(_, dst, src, sbc::AssignKind::Move) => {
let mty = &self.locals[*dst].mty;
let llty = self.locals[*dst].llty;
let dst_llval = self.locals[*dst].llval;
let src_llval = self.locals[*src].llval;

match mty {
mty::Type::Primitive(
mty::PrimitiveType::Bool
Expand All @@ -370,7 +381,8 @@ impl<'mm, 'up> FunctionContext<'mm, 'up> {
| mty::PrimitiveType::U128
| mty::PrimitiveType::U256,
) => {
builder.load_store(llty, src_llval, dst_llval);
let (load, store) = builder.load_store(llty, src_llval, dst_llval);
builder_di.create_load_store(instr_dbg, load, store, mty);
}
mty::Type::Reference(_, _) => {
builder.load_store(llty, src_llval, dst_llval);
Expand Down

0 comments on commit 1d1e920

Please sign in to comment.