Skip to content

Commit 4e13b65

Browse files
committed
aml: introduce 'transparent' reference types + handle undefined package elements
1 parent d45879d commit 4e13b65

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

aml/src/lib.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -707,11 +707,17 @@ impl Interpreter {
707707
Opcode::DataRegion => todo!(),
708708
Opcode::Local(local) => {
709709
let local = context.locals[local as usize].clone();
710-
context.last_op()?.arguments.push(Argument::Object(Arc::new(Object::Reference(local))));
710+
context.last_op()?.arguments.push(Argument::Object(Arc::new(Object::Reference {
711+
kind: ReferenceKind::LocalOrArg,
712+
inner: local,
713+
})));
711714
}
712715
Opcode::Arg(arg) => {
713716
let arg = context.args[arg as usize].clone();
714-
context.last_op()?.arguments.push(Argument::Object(Arc::new(Object::Reference(arg))));
717+
context.last_op()?.arguments.push(Argument::Object(Arc::new(Object::Reference {
718+
kind: ReferenceKind::LocalOrArg,
719+
inner: arg,
720+
})));
715721
}
716722
Opcode::Store => context.start_in_flight_op(OpInFlight::new(Opcode::Store, 2)),
717723
Opcode::RefOf => todo!(),
@@ -725,15 +731,28 @@ impl Interpreter {
725731
context.current_block.pc -= 1;
726732
let name = context.namestring()?;
727733

728-
let (_, object) = self.namespace.lock().search(&name, &context.current_scope)?;
729-
if let Object::Method { flags, .. } = *object {
730-
context.start_in_flight_op(OpInFlight::new_with(
731-
Opcode::InternalMethodCall,
732-
flags.arg_count(),
733-
))
734-
} else {
735-
context.last_op()?.arguments.push(Argument::Object(object));
734+
match self.namespace.lock().search(&name, &context.current_scope) {
735+
Ok((resolved_name, object)) => {
736+
if let Object::Method { flags, .. } = *object {
737+
context.start_in_flight_op(OpInFlight::new_with(
738+
Opcode::InternalMethodCall,
736739
vec![Argument::Object(object), Argument::Namestring(resolved_name)],
740+
flags.arg_count(),
741+
))
742+
} else {
743+
context.last_op()?.arguments.push(Argument::Object(object));
744+
}
745+
}
746+
Err(AmlError::ObjectDoesNotExist(_)) => {
747+
if context.current_block.kind == BlockKind::Package {
748+
let reference = Object::Reference {
749+
kind: ReferenceKind::Unresolved,
750+
inner: Arc::new(Object::String(name.to_string())),
751+
};
752+
context.last_op()?.arguments.push(Argument::Object(Arc::new(reference)));
753+
}
754+
}
755+
Err(other) => Err(other)?,
737756
}
738757
}
739758

@@ -946,6 +965,7 @@ impl Interpreter {
946965
// TODO: convert object to be of the type of destination, in line with 19.3.5 of the spec
947966
// TODO: write the object to the destination, including e.g. field writes that then lead to
948967
// literally god knows what.
968+
let object = object.unwrap_transparent_reference();
949969
match target {
950970
Argument::Object(target) => match target.gain_mut() {
951971
Object::Integer(target) => match object.gain_mut() {

aml/src/object.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub enum Object {
1313
Integer(u64),
1414
Method { code: Vec<u8>, flags: MethodFlags },
1515
Mutex { sync_level: u8 },
16-
Reference(Arc<Object>),
16+
Reference { kind: ReferenceKind, inner: Arc<Object> },
1717
OpRegion(OpRegion),
1818
Package(Vec<Arc<Object>>),
1919
PowerResource { system_level: u8, resource_order: u16 },
@@ -77,7 +77,7 @@ impl Object {
7777
Object::Integer(_) => ObjectType::Integer,
7878
Object::Method { .. } => ObjectType::Method,
7979
Object::Mutex { .. } => ObjectType::Mutex,
80-
Object::Reference(object) => object.typ(),
80+
Object::Reference { inner, .. } => inner.typ(),
8181
Object::OpRegion(_) => ObjectType::OpRegion,
8282
Object::Package(_) => ObjectType::Package,
8383
Object::PowerResource { .. } => ObjectType::PowerResource,
@@ -87,6 +87,35 @@ impl Object {
8787
Object::ThermalZone => ObjectType::ThermalZone,
8888
}
8989
}
90+
91+
pub fn unwrap_reference(self: Arc<Object>) -> Arc<Object> {
92+
let mut object = self;
93+
loop {
94+
if let Object::Reference { ref inner, .. } = *object {
95+
object = inner.clone();
96+
} else {
97+
return object.clone();
98+
}
99+
}
100+
}
101+
102+
/// Unwraps 'transparent' references (e.g. locals, arguments, and internal usage of reference-type objects), but maintain 'real'
103+
/// references deliberately created by AML.
104+
pub fn unwrap_transparent_reference(self: Arc<Self>) -> Arc<Object> {
105+
let mut object = self;
106+
loop {
107+
// TODO: what should this do with unresolved namestrings? It would need namespace
108+
// access to resolve them (and then this would probs have to move to a method on
109+
// `Interpreter`)?
110+
if let Object::Reference { kind, ref inner } = *object
111+
&& kind == ReferenceKind::LocalOrArg
112+
{
113+
object = inner.clone();
114+
} else {
115+
return object.clone();
116+
}
117+
}
118+
}
90119
}
91120

92121
#[derive(Debug)]
@@ -113,6 +142,12 @@ impl MethodFlags {
113142
}
114143
}
115144

145+
#[derive(Clone, Copy, PartialEq, Debug)]
146+
pub enum ReferenceKind {
147+
LocalOrArg,
148+
Unresolved,
149+
}
150+
116151
#[derive(Clone, Copy, PartialEq, Debug)]
117152
pub enum ObjectType {
118153
Uninitialized,

0 commit comments

Comments
 (0)