Represent register taking

This commit is contained in:
Andrew Morris
2023-06-20 16:57:49 +10:00
parent 39ccf8f35c
commit 72f9fbf0f7
11 changed files with 143 additions and 87 deletions

View File

@@ -1,6 +1,8 @@
use num_bigint::BigInt;
use valuescript_common::InstructionByte;
use crate::assembler::ValueType;
#[derive(Debug, Clone)]
pub struct Module {
pub export_default: Value,
@@ -163,32 +165,74 @@ impl std::fmt::Display for Class {
}
#[derive(Hash, PartialEq, Eq, Clone, Debug)]
pub enum Register {
Return,
This,
Named(String),
Ignore,
pub struct Register {
pub take: bool,
pub name: String,
}
impl Register {
pub fn as_name(&self) -> String {
match self {
Register::Return => "return".to_string(),
Register::This => "this".to_string(),
Register::Named(name) => name.clone(),
Register::Ignore => "ignore".to_string(),
pub fn return_(take: bool) -> Self {
Register {
take,
name: "return".to_string(),
}
}
pub fn this(take: bool) -> Self {
Register {
take,
name: "this".to_string(),
}
}
pub fn named(take: bool, name: String) -> Self {
Register { take, name }
}
pub fn ignore(take: bool) -> Self {
Register {
take,
name: "ignore".to_string(),
}
}
pub fn is_return(&self) -> bool {
return self.name == "return";
}
pub fn is_this(&self) -> bool {
return self.name == "this";
}
pub fn is_named(&self) -> bool {
match self.name.as_str() {
"return" | "this" | "ignore" => false,
_ => true,
}
}
pub fn is_ignore(&self) -> bool {
return self.name == "ignore";
}
pub fn value_type(&self) -> ValueType {
if self.take {
ValueType::TakeRegister
} else {
ValueType::Register
}
}
}
impl std::fmt::Display for Register {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Register::Return => write!(f, "%return"),
Register::This => write!(f, "%this"),
Register::Named(name) => write!(f, "%{}", name),
Register::Ignore => write!(f, "%ignore"),
write!(f, "%")?;
if self.take {
write!(f, "!")?;
}
write!(f, "{}", self.name)
}
}

View File

@@ -261,7 +261,7 @@ impl Assembler {
fn value(&mut self, value: &Value) {
match value {
Value::Register(register) => {
self.output.push(ValueType::Register as u8);
self.output.push(register.value_type() as u8);
self.register(register);
}
Value::Number(number) => self.number(*number),
@@ -294,19 +294,22 @@ impl Assembler {
}
fn lookup_register(&mut self, register: &Register) -> u8 {
match register {
Register::Return => 0,
Register::This => 1,
Register::Named(_) => match self.fn_data.register_map.get(register) {
match register.name.as_str() {
"return" => 0,
"this" => 1,
"ignore" => 0xff,
_ => match self.fn_data.register_map.get(&register.name) {
Some(index) => *index,
None => {
// TODO: Support >255 registers
let index = (self.fn_data.register_map.len() as u8) + 2;
self.fn_data.register_map.insert(register.clone(), index);
self
.fn_data
.register_map
.insert(register.name.clone(), index);
index
}
},
Register::Ignore => 0xff,
}
}
@@ -407,7 +410,7 @@ impl Assembler {
}
}
enum ValueType {
pub enum ValueType {
End = 0x00,
Void = 0x01,
Undefined = 0x02,
@@ -423,12 +426,13 @@ enum ValueType {
// Instance = 0x0c,
Pointer = 0x0d,
Register = 0x0e,
// External = 0x0f,
TakeRegister = 0x0f,
Builtin = 0x10,
Class = 0x11,
Lazy = 0x12,
BigInt = 0x13,
GeneratorFunction = 0x14,
// External = TBD,
}
#[derive(Hash, PartialEq, Eq, Clone)]
@@ -480,7 +484,7 @@ impl LocationMap {
#[derive(Default)]
struct AssemblerFnData {
register_map: HashMap<Register, u8>,
register_map: HashMap<String, u8>,
register_count_pos: usize,
labels_map: LocationMap,
}

View File

@@ -415,11 +415,13 @@ impl<'a> AssemblyParser<'a> {
panic!("Expected this to be impossible");
}
let take = self.parse_one_of(&["!", ""]) == "!";
let param_name = self.parse_identifier();
function
.parameters
.push(Register::Named(param_name.clone()));
.push(Register::named(take, param_name.clone()));
next = self.parse_one_of(&[",", ")"]);
@@ -811,14 +813,10 @@ impl<'a> AssemblyParser<'a> {
fn assemble_register(&mut self) -> Register {
self.parse_optional_whitespace();
self.parse_exact("%");
let take = self.parse_one_of(&["!", ""]) == "!";
let name = self.parse_identifier();
match name.as_str() {
"return" => Register::Return,
"this" => Register::This,
"ignore" => Register::Ignore,
_ => Register::Named(name),
}
return Register { take, name };
}
fn assemble_builtin(&mut self) -> Builtin {

View File

@@ -87,7 +87,7 @@ impl<'a> ExpressionCompiler<'a> {
match expr {
This(_) => {
return self.inline(Value::Register(Register::This), target_register);
return self.inline(Value::Register(Register::this(false)), target_register);
}
Array(array_exp) => {
return self.array_expression(array_exp, target_register);
@@ -1307,7 +1307,7 @@ impl<'a> ExpressionCompiler<'a> {
self.fnc.push(Instruction::Yield(
Value::Register(dst.clone()),
Register::Ignore,
Register::ignore(false),
));
self.fnc.label(next_label);
@@ -1572,7 +1572,7 @@ impl<'a> ExpressionCompiler<'a> {
name: self
.fnc
.label_allocator
.allocate(&format!("{}_initialized", register.as_name())),
.allocate(&format!("{}_initialized", register.name)),
};
self.fnc.push(Instruction::OpTripleNe(

View File

@@ -313,7 +313,7 @@ impl FunctionCompiler {
swc_ecma_ast::BlockStmtOrExpr::Expr(expr) => {
let mut expression_compiler = ExpressionCompiler { fnc: self };
expression_compiler.compile(expr, Some(Register::Return));
expression_compiler.compile(expr, Some(Register::return_(false)));
}
},
Functionish::Constructor(member_initializers_assembly, _class_span, constructor) => {
@@ -467,7 +467,7 @@ impl FunctionCompiler {
Some(expr) => {
let mut expression_compiler = ExpressionCompiler { fnc: self };
let compiled = expression_compiler.compile(expr, Some(Register::Return));
let compiled = expression_compiler.compile(expr, Some(Register::return_(false)));
self.use_(compiled);
}
}
@@ -676,7 +676,7 @@ impl FunctionCompiler {
.param
{
Some(_) => self.allocate_numbered_reg("_error"),
None => Register::Ignore,
None => Register::ignore(false),
};
catch_error_reg = Some(reg.clone());
@@ -695,12 +695,11 @@ impl FunctionCompiler {
let snap_registers: HashSet<Register> = self.get_mutated_registers(try_.block.span);
for reg in snap_registers {
let reg_name = match &reg {
Register::Named(name) => name,
_ => continue,
};
if !reg.is_named() {
continue;
}
let snap_reg = self.allocate_reg_fresh(&format!("snap_{}", reg_name));
let snap_reg = self.allocate_reg_fresh(&format!("snap_{}", reg.name));
self.push(Instruction::Mov(
Value::Register(reg.clone()),

View File

@@ -1,6 +1,4 @@
use crate::asm::{
Definition, DefinitionContent, Instruction, InstructionOrLabel, Pointer, Register, Value,
};
use crate::asm::{Definition, DefinitionContent, Instruction, InstructionOrLabel, Pointer, Value};
pub struct ImportPattern {
pub pointer: Pointer,
@@ -31,8 +29,14 @@ impl ImportPattern {
};
let (path_value, is_star) = match first_instruction {
Instruction::Import(path, Register::Return) => (path, false),
Instruction::ImportStar(path, Register::Return) => (path, true),
Instruction::Import(path, reg) => match reg.name.as_str() {
"return" => (path, false),
_ => return None,
},
Instruction::ImportStar(path, reg) => match reg.name.as_str() {
"return" => (path, true),
_ => return None,
},
_ => return None,
};
@@ -67,15 +71,16 @@ impl ImportPattern {
};
match second_instruction {
Instruction::Sub(
Value::Register(Register::Return),
Value::String(name),
Register::Return,
) => Some(ImportPattern {
pointer: definition.pointer.clone(),
path: path.clone(),
kind: ImportKind::Name(name.clone()),
}),
Instruction::Sub(Value::Register(obj), Value::String(name), target) => {
match obj.name == "return" && target.name == "return" {
true => Some(ImportPattern {
pointer: definition.pointer.clone(),
path: path.clone(),
kind: ImportKind::Name(name.clone()),
}),
false => None,
}
}
_ => None,
}
}

View File

@@ -1,4 +1,4 @@
use crate::asm::{Instruction, Register, Value};
use crate::asm::{Instruction, Value};
pub fn instruction_mutates_this(instruction: &Instruction) -> bool {
use Instruction::*;
@@ -50,17 +50,15 @@ pub fn instruction_mutates_this(instruction: &Instruction) -> bool {
| ConstSubCall(_, _, _, reg)
| ThisSubCall(_, _, _, reg)
| Cat(_, reg)
| Yield(_, reg) => reg == &Register::This,
| Yield(_, reg) => reg.is_this(),
Next(iter, res) => iter == &Register::This || res == &Register::This,
UnpackIterRes(_, value_reg, done_reg) => {
value_reg == &Register::This || done_reg == &Register::This
}
Next(iter, res) => iter.is_this() || res.is_this(),
UnpackIterRes(_, value_reg, done_reg) => value_reg.is_this() || done_reg.is_this(),
Apply(_, ctx, _, reg) | SubCall(ctx, _, _, reg) | YieldStar(ctx, reg) => {
reg == &Register::This
reg.is_this()
|| match ctx {
Value::Register(reg) => reg == &Register::This,
Value::Register(reg) => reg.is_this(),
_ => false,
}
}

View File

@@ -408,17 +408,17 @@ impl ModuleCompiler {
body: match orig_name.sym.to_string() == "default" {
true => vec![InstructionOrLabel::Instruction(Instruction::Import(
Value::String(src.value.to_string()),
Register::Return,
Register::return_(false),
))],
false => vec![
InstructionOrLabel::Instruction(Instruction::ImportStar(
Value::String(src.value.to_string()),
Register::Return,
Register::return_(false),
)),
InstructionOrLabel::Instruction(Instruction::Sub(
Value::Register(Register::Return),
Value::Register(Register::return_(false)),
Value::String(orig_name.sym.to_string()),
Register::Return,
Register::return_(false),
)),
],
},
@@ -501,7 +501,7 @@ impl ModuleCompiler {
content: DefinitionContent::Lazy(Lazy {
body: vec![InstructionOrLabel::Instruction(Instruction::ImportStar(
Value::String(src),
Register::Return,
Register::return_(false),
))],
}),
});
@@ -574,12 +574,12 @@ impl ModuleCompiler {
body: vec![
InstructionOrLabel::Instruction(Instruction::ImportStar(
Value::String(import_path.clone()),
Register::Return,
Register::return_(false),
)),
InstructionOrLabel::Instruction(Instruction::Sub(
Value::Register(Register::Return),
Value::Register(Register::return_(false)),
Value::String(external_name),
Register::Return,
Register::return_(false),
)),
],
}),
@@ -609,7 +609,7 @@ impl ModuleCompiler {
content: DefinitionContent::Lazy(Lazy {
body: vec![InstructionOrLabel::Instruction(Instruction::Import(
Value::String(import_path.clone()),
Register::Return,
Register::return_(false),
))],
}),
});
@@ -638,7 +638,7 @@ impl ModuleCompiler {
content: DefinitionContent::Lazy(Lazy {
body: vec![InstructionOrLabel::Instruction(Instruction::ImportStar(
Value::String(import_path.clone()),
Register::Return,
Register::return_(false),
))],
}),
});
@@ -728,8 +728,11 @@ impl ModuleCompiler {
let key_asm = ec.fnc.use_(compiled_key);
let value_asm = ec.fnc.use_(compiled_value);
ec.fnc
.push(Instruction::SubMov(key_asm, value_asm, Register::This));
ec.fnc.push(Instruction::SubMov(
key_asm,
value_asm,
Register::this(false),
));
}
swc_ecma_ast::ClassMember::PrivateProp(private_prop) => {
self.todo(private_prop.span, "private props")

View File

@@ -125,28 +125,28 @@ pub struct RegAllocator {
impl RegAllocator {
pub fn allocate(&mut self, based_on_name: &str) -> Register {
let name = self.alloc.allocate(&based_on_name.to_string());
Register::Named(name)
Register::named(false, name)
}
pub fn allocate_fresh(&mut self, based_on_name: &str) -> Register {
let name = self.alloc.allocate_fresh(&based_on_name.to_string());
Register::Named(name)
Register::named(false, name)
}
pub fn allocate_numbered(&mut self, prefix: &str) -> Register {
let name = self.alloc.allocate_numbered(&prefix.to_string());
Register::Named(name)
Register::named(false, name)
}
pub fn allocate_numbered_fresh(&mut self, prefix: &str) -> Register {
let name = self.alloc.allocate_numbered_fresh(&prefix.to_string());
Register::Named(name)
Register::named(false, name)
}
pub fn release(&mut self, reg: &Register) {
match reg {
Register::Named(name) => self.alloc.release(name),
_ => panic!("Can't release non-named register"),
match reg.is_named() {
true => self.alloc.release(&reg.name),
false => panic!("Can't release non-named register"),
}
}
}

View File

@@ -40,7 +40,7 @@ impl TargetAccessor {
return match expr {
Ident(ident) => TargetAccessor::compile_ident(ec, ident),
This(_) => TargetAccessor::Register(Register::This),
This(_) => TargetAccessor::Register(Register::this(false)),
Member(member) => {
let obj = TargetAccessor::compile(ec, &member.obj, false);
let subscript = ec.member_prop(&member.prop, None);
@@ -189,7 +189,7 @@ impl TargetAccessor {
pub fn targets_this(&self) -> bool {
return match self {
TargetAccessor::Register(reg) => reg == &Register::This,
TargetAccessor::Register(reg) => reg == &Register::this(false),
TargetAccessor::Nested(nta) => nta.obj.targets_this(),
};
}