tamer: asg: Hoist Root from Ident into Object

This was always the intent, but I didn't have a higher-level object
yet.  This removes all the awkwardness that existed with working the root
in as an identifier.

DEV-11864
main
Mike Gerwitz 2022-05-19 12:48:43 -04:00
parent 6252758730
commit 958a707e02
6 changed files with 27 additions and 52 deletions

View File

@ -118,7 +118,7 @@ impl Asg {
// Automatically add the root which will be used to determine what
// identifiers ought to be retained by the final program.
// This is not indexed and is not accessable by name.
let root_node = graph.add_node(Some(Ident::Root.into()));
let root_node = graph.add_node(Some(Object::Root));
Self {
graph,

View File

@ -75,18 +75,6 @@ pub enum Ident {
/// [linker][crate::ld] to put them into the correct order for the
/// final executable.
IdentFragment(SymbolId, IdentKind, Source, FragmentText),
/// Represents the root of all reachable identifiers.
///
/// Any identifier not reachable from the root will not be linked into
/// the final executable.
///
/// There should be only one identifier of this kind.
///
/// TODO: This is _not_ an identifier;
/// once the ASG supports other types,
/// do not associate with identifiers.
Root,
}
impl Ident {
@ -97,11 +85,6 @@ impl Ident {
| Self::Ident(name, ..)
| Self::Extern(name, ..)
| Self::IdentFragment(name, ..) => *name,
// This should never be called,
// and can go away when we can stop pretending that the root
// is an identifier.
Self::Root => unimplemented!("Ident::name for Root"),
}
}
@ -117,8 +100,6 @@ impl Ident {
Self::Ident(_, kind, ..)
| Self::Extern(_, kind, ..)
| Self::IdentFragment(_, kind, ..) => Some(kind),
Self::Root => None,
}
}
@ -129,7 +110,7 @@ impl Ident {
/// [`None`] is returned.
pub fn src(&self) -> Option<&Source> {
match self {
Self::Missing(..) | Self::Extern(..) | Self::Root => None,
Self::Missing(..) | Self::Extern(..) => None,
Self::Ident(_, _, src, ..) | Self::IdentFragment(_, _, src, ..) => {
Some(src)
@ -143,10 +124,7 @@ impl Ident {
/// [`None`] is returned.
pub fn fragment(&self) -> Option<FragmentText> {
match self {
Self::Missing(..)
| Self::Ident(..)
| Self::Extern(..)
| Self::Root => None,
Self::Missing(..) | Self::Ident(..) | Self::Extern(..) => None,
Self::IdentFragment(_, _, _, text) => Some(*text),
}
@ -309,11 +287,6 @@ impl Ident {
}
Ident::Ident(..) | Ident::IdentFragment(..) => Ok(self),
// This should never be called.
Ident::Root => {
unimplemented!("Ident::resolved on Root")
}
}
}

View File

@ -24,6 +24,15 @@ use super::Ident;
/// Some object on the ASG.
#[derive(Debug, PartialEq)]
pub enum Object {
/// Represents the root of all reachable identifiers.
///
/// Any identifier not reachable from the root will not be linked into
/// the final executable.
///
/// There should be only one object of this kind.
Root,
/// Identifier (a named object).
Ident(Ident),
}
@ -33,6 +42,7 @@ impl Object {
pub fn as_ident_ref(&self) -> Option<&Ident> {
match self {
Self::Ident(ident) => Some(ident),
_ => None,
}
}
@ -47,6 +57,7 @@ impl Object {
pub fn unwrap_ident(self) -> Ident {
match self {
Self::Ident(ident) => ident,
x => panic!("internal error: expected Ident, found {x:?}"),
}
}
@ -61,6 +72,7 @@ impl Object {
pub fn unwrap_ident_ref(&self) -> &Ident {
match self {
Self::Ident(ident) => ident,
x => panic!("internal error: expected Ident, found {x:?}"),
}
}
}

View File

@ -118,6 +118,7 @@ pub fn xmle(package_path: &str, output: &str) -> Result<(), TameldError> {
Ok(())
}
// TODO: This needs to be further generalized.
pub fn graphml(package_path: &str, output: &str) -> Result<(), TameldError> {
let mut fs = VisitOnceFilesystem::new();
let mut depgraph = LinkerAsg::with_capacity(65536, 65536);
@ -150,6 +151,12 @@ pub fn graphml(package_path: &str, output: &str) -> Result<(), TameldError> {
format!("{}", generated),
)
}
// TODO: We want these filtered.
Some(_) => (
String::from("non-ident"),
"non-ident".into(),
"false".into(),
),
None => (
String::from("missing"),
"missing".into(),

View File

@ -23,7 +23,7 @@
use super::section::{SectionsError, XmleSections};
use crate::{
asg::{Asg, Ident, IdentKind, ObjectRef},
asg::{Asg, Ident, IdentKind, Object, ObjectRef},
sym::{st, GlobalSymbolResolve, SymbolId},
};
use petgraph::visit::DfsPostOrder;
@ -54,8 +54,10 @@ where
dest.push(get_ident(asg, st::L_RETMAP_UUUHEAD))?;
while let Some(index) = dfs.next(&asg.graph) {
let ident = asg.get(index).expect("missing node");
dest.push(ident.unwrap_ident_ref())?;
match asg.get(index).expect("missing object") {
Object::Root => (),
Object::Ident(ident) => dest.push(ident)?,
}
}
dest.push(get_ident(asg, st::L_MAP_UUUTAIL))?;
@ -287,10 +289,6 @@ mod test {
asg.get_ident(adepdep),
asg.get_ident(adep),
asg.get_ident(a),
// TODO: This will go away once Root is no longer considered
// an identifier.
// The real Sections filters this out.
Some(&Ident::Root),
// Static tail
asg.lookup(st::L_MAP_UUUTAIL.into())
.and_then(|id| asg.get_ident(id)),

View File

@ -106,11 +106,6 @@ impl<'a> Sections<'a> {
impl<'a> XmleSections<'a> for Sections<'a> {
fn push(&mut self, ident: &'a Ident) -> PushResult {
// TODO: This can go away once we stop treating root as an ident
if matches!(ident, Ident::Root) {
return Ok(());
}
self.deps.push(ident);
// TODO: This cannot happen, so use an API without Option.
@ -309,16 +304,6 @@ mod test {
Ok(())
}
// TODO: This can be removed once we no longer treat Root as an
// identifier.
#[test]
fn push_ignores_root() {
let mut sut = Sut::new();
sut.push(&Ident::Root).unwrap();
assert!(sut.take_deps().is_empty());
}
// Certain identifiers have no fragments because the code is associated
// with their parents (for now, anyway).
#[test]