Skip to content

Commit

Permalink
feat(jsruntime): VariableStatement
Browse files Browse the repository at this point in the history
  • Loading branch information
masnagam committed Dec 17, 2024
1 parent 294ad10 commit 14c682d
Show file tree
Hide file tree
Showing 17 changed files with 359 additions and 67 deletions.
10 changes: 10 additions & 0 deletions libs/jsruntime/src/llvmir/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct RuntimeFunctions {
print_u32: unsafe extern "C" fn(*mut c_void, u32, *const c_char),
print_f64: unsafe extern "C" fn(*mut c_void, f64, *const c_char),
print_value: unsafe extern "C" fn(*mut c_void, *const Value, *const c_char),
print_message: unsafe extern "C" fn(*mut c_void, *const c_char),
launch_debugger: unsafe extern "C" fn(*mut c_void),
}

Expand All @@ -63,6 +64,7 @@ impl RuntimeFunctions {
print_u32: runtime_print_u32,
print_f64: runtime_print_f64,
print_value: runtime_print_value,
print_message: runtime_print_message,
launch_debugger: runtime_launch_debugger,
}
}
Expand Down Expand Up @@ -419,6 +421,14 @@ unsafe extern "C" fn runtime_print_value(
}
}

unsafe extern "C" fn runtime_print_message(
_runtime: *mut c_void,
msg: *const std::os::raw::c_char,
) {
let msg = std::ffi::CStr::from_ptr(msg);
logger::debug!("runtime_print_value: {msg:?}");
}

unsafe extern "C" fn runtime_launch_debugger(_runtime: *mut c_void) {
logger::debug!("runtime_launch_debugger");
// TODO(feat): Support debuggers such as Chrome DevTools.
Expand Down
8 changes: 8 additions & 0 deletions libs/jsruntime/src/llvmir/compiler/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,13 @@ impl CompilerBridge {
}
}

#[allow(unused)]
pub fn create_print_message(&self, msg: &CStr) {
unsafe {
compiler_peer_create_print_message(self.0, msg.as_ptr());
}
}

// debugger

pub fn create_debugger(&self) {
Expand Down Expand Up @@ -1670,6 +1677,7 @@ extern "C" {
// print

fn compiler_peer_create_print_value(peer: CompilerPeer, value: ValueIrPtr, msg: *const c_char);
fn compiler_peer_create_print_message(peer: CompilerPeer, msg: *const c_char);

// debugger

Expand Down
6 changes: 6 additions & 0 deletions libs/jsruntime/src/llvmir/compiler/impl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,12 @@ class Compiler {
builder_->CreateCall(func, {runtime_, value, msg_value});
}

void CreatePrintMessage(const char* msg = "") {
auto* msg_value = builder_->CreateGlobalString(msg, REG_NAME("runtime.print_message.msg"));
auto* func = types_->CreateRuntimePrintMessage();
builder_->CreateCall(func, {runtime_, msg_value});
}

// debugger

void CreateDebugger() {
Expand Down
58 changes: 37 additions & 21 deletions libs/jsruntime/src/llvmir/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl<'r, 's> Compiler<'r, 's> {
CompileCommand::AllocateLocals(num_locals) => self.process_allocate_locals(*num_locals),
CompileCommand::MutableBinding => self.process_mutable_binding(),
CompileCommand::ImmutableBinding => self.process_immutable_binding(),
CompileCommand::DeclareFunction => self.process_declare_function(),
CompileCommand::DeclareVars(scope_ref) => self.process_declare_vars(*scope_ref),
CompileCommand::DeclareClosure => self.process_declare_closure(),
CompileCommand::Call(nargs) => self.process_call(*nargs),
CompileCommand::PushScope(scope_ref) => self.process_push_scope(*scope_ref),
Expand Down Expand Up @@ -548,7 +548,7 @@ impl<'r, 's> Compiler<'r, 's> {
}

fn dereference(&mut self) -> (Operand, Option<(Symbol, Locator)>) {
logger::debug!(event = "dereference");
logger::debug!(event = "dereference", operand_stack.top=?self.operand_stack.last());

let operand = self.operand_stack.pop().unwrap();
match operand {
Expand Down Expand Up @@ -626,22 +626,33 @@ impl<'r, 's> Compiler<'r, 's> {
self.create_store_operand_to_value(&operand, value);
}

fn process_declare_function(&mut self) {
let block = self.control_flow_stack.scope_flow().hoisted_block;
fn process_declare_vars(&mut self, scope_ref: ScopeRef) {
debug_assert!(self.scope_tree.scope(scope_ref).is_function());

// In the specification, function-scoped variables defined by "VariableStatement"s are
// created in "10.2.11 FunctionDeclarationInstantiation ( func, argumentsList )". We
// create them here for simplicity but this still works properly for well-formed JavaScript
// programs.
//
// Function-scoped variables are created in the `init` basic block of the current scope.
// The `init` basic block is performed before the `hoisted` basic block on which inner
// functions defined by "FunctionDeclaration"s are created.
let block = self.control_flow_stack.scope_flow().init_block;

let backup = self.bridge.get_basic_block();
self.bridge.set_basic_block(block);

let (operand, _) = self.dereference();
// TODO: operand must hold a lambda.
let (_symbol, locator) = self.pop_reference();

let value = match locator {
Locator::Local(index) => self.locals[index as usize],
_ => unreachable!(),
};

self.create_store_operand_to_value(&operand, value);
// TODO(refactor): inefficient
for (binding_ref, binding) in self.scope_tree.iter_bindings(scope_ref) {
if !binding.is_function_scoped() {
continue;
}
let value = match self.scope_tree.compute_locator(binding_ref) {
Locator::Local(index) => self.locals[index as usize],
locator => unreachable!("{locator:?}"),
};
self.bridge.create_store_undefined_to_value(value);
}

self.bridge.set_basic_block(backup);
}
Expand All @@ -654,15 +665,20 @@ impl<'r, 's> Compiler<'r, 's> {

let (operand, _) = self.dereference();
// TODO: operand must hold a closure.
let (_symbol, locator) = self.pop_reference();
let (symbol, locator) = self.pop_reference();

let value = match locator {
Locator::Local(index) => self.locals[index as usize],
_ => unreachable!(),
match locator {
Locator::Local(index) => {
let value = self.locals[index as usize];
self.create_store_operand_to_value(&operand, value);
}
Locator::Global => {
let value = self.create_to_any(&operand);
self.bridge.create_set(symbol, value);
}
_ => unreachable!("{locator:?}"),
};

self.create_store_operand_to_value(&operand, value);

self.bridge.set_basic_block(backup);
}

Expand Down Expand Up @@ -800,7 +816,7 @@ impl<'r, 's> Compiler<'r, 's> {

let scope = self.scope_tree.scope(scope_ref);
for binding in scope.bindings.iter() {
if binding.is_hidden() {
if binding.is_hidden() || binding.is_function_scoped() {
continue;
}
let locator = binding.locator();
Expand Down
4 changes: 4 additions & 0 deletions libs/jsruntime/src/llvmir/compiler/peer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,10 @@ void compiler_peer_create_print_value(CompilerPeer peer, ValueIrPtr value, const
IMPL(peer)->CreatePrintValue(LLVM_VALUE(value), msg);
}

void compiler_peer_create_print_message(CompilerPeer peer, const char* msg) {
IMPL(peer)->CreatePrintMessage(msg);
}

// debugger

void compiler_peer_create_debugger(CompilerPeer peer) {
Expand Down
4 changes: 4 additions & 0 deletions libs/jsruntime/src/llvmir/runtime.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,9 @@ functions:
type: '&Value'
- name: msg
type: '&std::ffi::CStr'
- name: print_message
args:
- name: msg
type: '&std::ffi::CStr'
- name: launch_debugger
args: []
17 changes: 15 additions & 2 deletions libs/jsruntime/src/objects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,23 @@ impl Object {
.entry(name)
.and_modify(|prop| match prop {
Property::Data {
ref mut value,
// The variable name `value` is already used in the arguments.
//
// NOTE: Be careful. `clippy` does NOT detect mistakes like this:
//
// ```rust
// *value = value.clone();
// ```
//
// This does NOT match the `self_assignment` lint that is denied by default.
//
// If `Value` implements `Copy`, this kind of self-assignment can be detected
// if the `assigning_clones` lint is denied (but it's allowed by default).
value: ref mut value_ref,
flags,
} => {
debug_assert!(flags.contains(PropertyFlags::WRITABLE));
*value = value.clone();
*value_ref = value.clone();
}
Property::Accessor { flags } => {
debug_assert!(flags.contains(PropertyFlags::WRITABLE));
Expand All @@ -88,6 +100,7 @@ impl Object {
});
}

// TODO(feat): 10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current )
pub fn define_own_property(&mut self, name: Symbol, prop: Property) {
self.properties.insert(name, prop);
}
Expand Down
Loading

0 comments on commit 14c682d

Please sign in to comment.