Skip to content

Commit

Permalink
Add NEW instruction for datums (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimach authored May 2, 2022
1 parent 03dfd16 commit 662966e
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 3 deletions.
20 changes: 20 additions & 0 deletions src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,26 @@ impl<'ctx> CodeGen<'ctx, '_> {

self.stack().push(out_value);
}
DMIR::NewDatum(location) => {
let stack_pos = self.stack_loc.len() - 1 - *location as usize;
let t = self.stack_loc[stack_pos];
let type_meta = self.emit_load_meta_value(t);

let usr = func.get_nth_param(2).unwrap().into_struct_value();

let create_datum = self.module.get_function("dmir.runtime.create_datum").unwrap();
let result = self.builder.build_call(
create_datum,
&[
usr.into(),
type_meta.data.into(),
self.context.i32_type().const_int(0xFFFF as u64, false).into()
], "create_datum").as_any_value_enum().into_int_value();
let result_meta = MetaValue::with_tag(ValueTag::Datum, result.into(), self);
let r = self.emit_store_meta_value(result_meta);
self.stack_loc[stack_pos] = r;
self.stack().push(r);
}
DMIR::PushInt(val) => {
// val is int, so convert it to float as all values in byond are floats, then bit-cast to store it within DMValue
let value = self.builder.build_bitcast(
Expand Down
12 changes: 10 additions & 2 deletions src/dmir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub enum DMIR {
CheckTypeDeopt(u32, ValueTagPredicate, Box<DMIR>), // Doesn't consume stack value for now
CallProcById(ProcId, u8, u32),
CallProcByName(StringId, u8, u32),
NewDatum(u32),
IncRefCount { target: RefOpDisposition, op: Box<DMIR> },
DecRefCount { target: RefOpDisposition, op: Box<DMIR> },
Nop,
Expand Down Expand Up @@ -110,7 +111,7 @@ pub enum ValueLocation {
}

macro_rules! type_switch {
(@switch_counter $s:expr, @stack $n:literal, $(($($check:tt)+) => $body:expr),+) => ({
(@switch_counter $s:expr, @stack $n:expr, $(($($check:tt)+) => $body:expr),+) => ({
let cases = vec![
$((value_tag_pred!($($check)+), $body)),+
];
Expand Down Expand Up @@ -273,7 +274,7 @@ pub fn decode_byond_bytecode(nodes: Vec<Node<DebugData>>, proc: Proc) -> Result<
let mut switch_counter = 0;

macro_rules! build_type_switch {
(@stack $n:literal, $(($($check:tt)+) => $body:expr),+) => ({
(@stack $n:expr, $(($($check:tt)+) => $body:expr),+) => ({
type_switch!(@switch_counter &mut switch_counter, @stack $n, $(($($check)+) => $body),+)
});
}
Expand Down Expand Up @@ -725,6 +726,13 @@ pub fn decode_byond_bytecode(nodes: Vec<Node<DebugData>>, proc: Proc) -> Result<
irs.push(DMIR::Swap); // c (a+c) b
irs.push(DMIR::SwapX1); // (a+c) b c
}
Instruction::New(arg_count) => {
irs.append(&mut build_type_switch!(
@stack arg_count as u8,
(ValueTag::DatumTypepath) => vec![DMIR::NewDatum(arg_count), DMIR::CallProcByName(StringId(3), 6, arg_count), DMIR::Pop],
(@any) => deopt!(@type_switch)
));
}
Instruction::IterLoad(kind, bitmask) => {
irs.push(DMIR::IterAllocate);
match kind {
Expand Down
11 changes: 11 additions & 0 deletions src/pads/dm_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ byond_imports!(
unix => "8b b5 c8 f8 ff ff 89 54 24 08 89 4c 24 0c 89 7c 24 04 89 34 24 e8 >?? ?? ?? ?? 0f b6 c0 66 89 85 d6 f8 ff ff 8d bd f0 f8 ff ff df 85 d6 f8 ff ff d9 5c 24 04 89 3c 24",
windows => "ff b5 e0 fd ff ff ff 74 ca fc ff 74 ca f8 e8 >?? ?? ?? ?? 83 c4 10 0f b6 c0 66 0f 6e c0 51"
);
fn CREATE_DATUM_BY_TYPE: extern "cdecl" fn(Value, i32, i32) -> i32
= find_by_call!(
unix => "c7 44 24 0c ff ff 00 00 89 54 24 04 89 04 24 e8 >?? ?? ?? ?? 89 34 24 c7 44 24 08 21 00 00 00 89 44 24 04",
windows => "83 c4 08 eb 24 6a 21 68 ff ff 00 00 ff 76 04 ff 75 f8 ff 75 fc e8 >?? ?? ?? ?? 83 c4 10"
);
);

pub(crate) fn init() {
Expand All @@ -28,4 +33,10 @@ pub extern "cdecl" fn is_subtype_of(t: Value, value: Value) -> bool {
unsafe {
return IS_SUBTYPE_OF(t, value);
}
}

pub extern "cdecl" fn create_datum(usr: Value, t: i32, unk: i32) -> i32 {
unsafe {
return CREATE_DATUM_BY_TYPE(usr, t, unk);
}
}
1 change: 1 addition & 0 deletions src/pads/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ pub(crate) fn bind_runtime_externals(module: &Module, execution_engine: &Executi
use dm_types::*;
runtime_export!(is_dm_entity);
runtime_export!(is_subtype_of);
runtime_export!(create_datum);

use lists::*;
runtime_export!(list_associative_get);
Expand Down
7 changes: 7 additions & 0 deletions src/ref_count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,13 @@ impl<'t> Analyzer<'t> {
}
op_effect!(@move_in @stack);
}
DMIR::NewDatum(location) => {
let stack_pos = self.stack.len() - 1 - *location as usize;
let location_read = ValueLocation::Stack(*location as u8);
self.drains.push(RValueDrain::ConsumeDrain(pos, self.stack[stack_pos], DecRefOp::DupPost(location_read)));
self.stack[stack_pos] = mk_value!(self, RValue::MovedInSource(pos));
op_effect!(@produce @stack);
}
DMIR::End => {
unset_locals_and_cache!();
self.block_ended = true;
Expand Down
1 change: 1 addition & 0 deletions src/runtime.ll
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ declare external i32 @dmir.runtime.create_new_list(i32)

declare external i1 @dmir.runtime.is_dm_entity(%DMValue)
declare external i1 @dmir.runtime.is_subtype_of(%DMValue, %DMValue)
declare external i32 @dmir.runtime.create_datum(%DMValue, i32, i32)

declare external %DMValue @dmir.runtime.get_step(%DMValue, i8)

Expand Down
16 changes: 16 additions & 0 deletions tests/testData/test_new.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/proc/do_test()
compile_proc(/proc/new_datum)
CHECK_INSTALL_COMPILED // RES: /new_datum

RES(new_datum(2)) // RES: 2
RES(new_datum(8)) // RES: 8

/proc/new_datum(v)
var/datum/test/t = new /datum/test(v)
return t.a

/datum/test
var/a = 2

New(v)
a = v
3 changes: 2 additions & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ test_dm!(test_loops);
test_dm!(test_inc_dec);
test_dm!(test_step + "test_step.dmm");
test_dm!(test_iterator);
test_dm!(test_turf_iterator + "test_turf_iterator.dmm");
test_dm!(test_turf_iterator + "test_turf_iterator.dmm");
test_dm!(test_new);

0 comments on commit 662966e

Please sign in to comment.