Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
path: root/tamer
diff options
context:
space:
mode:
authorMike Gerwitz <mike.gerwitz@ryansg.com>2020-04-06 23:28:07 -0400
committerMike Gerwitz <mike.gerwitz@ryansg.com>2020-04-28 09:06:25 -0400
commit3f46917da9d42e7bf9fdbd5bad643d614090cb24 (patch)
treedf3c45dbf15cbd9c9d4aa12bae0994e2458619d8 /tamer
parent7ed0691c4561b4747bbbe37830961ae057d5aab3 (diff)
downloadtame-3f46917da9d42e7bf9fdbd5bad643d614090cb24.tar.gz
tame-3f46917da9d42e7bf9fdbd5bad643d614090cb24.tar.bz2
tame-3f46917da9d42e7bf9fdbd5bad643d614090cb24.zip
[DEV-7084] TAMER: AsgBuilder extracted from POC
This extracts the changes nearly verbatim before doing refactoring so that it's easier to observe what changes have been made.
Diffstat (limited to 'tamer')
-rw-r--r--tamer/src/ld/poc.rs120
-rw-r--r--tamer/src/obj/xmlo/asg_builder.rs183
-rw-r--r--tamer/src/obj/xmlo/mod.rs3
3 files changed, 200 insertions, 106 deletions
diff --git a/tamer/src/ld/poc.rs b/tamer/src/ld/poc.rs
index ef25659..38ac2b3 100644
--- a/tamer/src/ld/poc.rs
+++ b/tamer/src/ld/poc.rs
@@ -25,14 +25,14 @@ use crate::fs::{
};
use crate::global;
use crate::ir::asg::{
- Asg, AsgError, DefaultAsg, IdentKind, IdentObject, IdentObjectData,
- ObjectRef, Sections, SortableAsg, Source,
+ Asg, AsgError, DefaultAsg, IdentObject, IdentObjectData, ObjectRef,
+ Sections, SortableAsg,
};
use crate::obj::xmle::writer::XmleWriter;
-use crate::obj::xmlo::reader::{XmloError, XmloEvent, XmloReader};
+use crate::obj::xmlo::reader::{XmloError, XmloReader};
+use crate::obj::xmlo::{AsgBuilder, AsgBuilderResult};
use crate::sym::{DefaultInterner, Interner, Symbol};
-use fxhash::{FxBuildHasher, FxHashMap, FxHashSet};
-use std::convert::TryInto;
+use fxhash::{FxBuildHasher, FxHashMap};
use std::error::Error;
use std::fs;
use std::io::BufReader;
@@ -131,8 +131,6 @@ fn load_xmlo<'a, 'i, I: Interner<'i>>(
) -> LoadResult<'i> {
let first = fs.visit_len() == 0;
- let mut found: FxHashSet<&str> = Default::default();
-
let cfile: CanonicalFile<BufReader<fs::File>> = match fs.open(path_str)? {
VisitOnceFile::FirstVisit(file) => file,
VisitOnceFile::Visited => return Ok(None),
@@ -140,106 +138,16 @@ fn load_xmlo<'a, 'i, I: Interner<'i>>(
let (path, file) = cfile.into();
- let mut xmlo: XmloReader<'_, _, _> = (file, interner).into();
- let mut elig = None;
-
- let mut name: Option<&'i Symbol<'i>> = None;
- let mut relroot: Option<String> = None;
-
- loop {
- match xmlo.read_event() {
- Ok(XmloEvent::Package(attrs)) => {
- if first {
- name = attrs.name;
- relroot = attrs.relroot;
- }
- elig = attrs.elig;
- }
-
- Ok(XmloEvent::SymDeps(sym, deps)) => {
- // TODO: API needs to expose whether a symbol is already
- // known so that we can warn on them
-
- // Maps should not pull in symbols since we may end up
- // mapping to params that are never actually used
- if !sym.starts_with(":map:") {
- for dep_sym in deps {
- depgraph.add_dep_lookup(sym, dep_sym);
- }
- }
- }
-
- Ok(XmloEvent::SymDecl(sym, attrs)) => {
- if let Some(sym_src) = attrs.src {
- found.insert(sym_src);
- } else {
- let owned = attrs.src.is_none();
- let extern_ = attrs.extern_;
-
- let kind = (&attrs).try_into().map_err(|err| {
- format!("sym `{}` attrs error: {}", sym, err)
- });
-
- let mut src: Source = attrs.into();
-
- // Existing convention is to omit @src of local package
- // (in this case, the program being linked)
- if first {
- src.pkg_name = None;
- }
-
- match kind {
- Ok(kindval) => {
- // TODO: inefficient
- let link_root = owned
- && (kindval == IdentKind::Meta
- || kindval == IdentKind::Map
- || kindval == IdentKind::RetMap);
-
- if extern_ {
- depgraph.declare_extern(sym, kindval, src)?;
- } else {
- let node =
- depgraph.declare(sym, kindval, src)?;
-
- if link_root {
- roots.push(node);
- }
- }
- }
- Err(e) => return Err(e.into()),
- };
- }
- }
-
- Ok(XmloEvent::Fragment(sym, text)) => {
- match depgraph.lookup(sym) {
- Some(frag) => match depgraph.set_fragment(frag, text) {
- Ok(_) => (),
- Err(e) => return Err(e.into()),
- },
- None => {
- return Err(XmloError::MissingFragment(String::from(
- "missing fragment",
- ))
- .into());
- }
- };
- }
-
- // We don't need to read any further than the end of the
- // header (symtable, sym-deps, fragments)
- Ok(XmloEvent::Eoh) => break,
-
- Err(e) => return Err(e.into()),
- }
- }
+ let xmlo: XmloReader<'_, _, _> = (file, interner).into();
- if let Some(elig_sym) = elig {
- roots.push(depgraph.lookup(elig_sym).expect(
- "internal error: package elig references nonexistant symbol",
- ));
- }
+ let AsgBuilderResult::<'i, FxBuildHasher, _> {
+ found,
+ roots: mut pkgroots,
+ name,
+ relroot,
+ } = xmlo.build(depgraph, first)?;
+
+ roots.append(&mut pkgroots);
let mut dir: PathBuf = path.clone();
dir.pop();
diff --git a/tamer/src/obj/xmlo/asg_builder.rs b/tamer/src/obj/xmlo/asg_builder.rs
new file mode 100644
index 0000000..af37b58
--- /dev/null
+++ b/tamer/src/obj/xmlo/asg_builder.rs
@@ -0,0 +1,183 @@
+// Read from xmlo and immediately lower to ASG IR
+//
+// Copyright (C) 2014-2020 Ryan Specialty Group, LLC.
+//
+// This file is part of TAME.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use super::reader::{XmloError, XmloEvent, XmloReader};
+use crate::ir::asg::{Asg, IdentKind, IdentObjectState, ObjectRef, Source};
+use crate::sym::{Interner, Symbol};
+use petgraph::graph::IndexType;
+use std::convert::TryInto;
+use std::error::Error;
+use std::hash::BuildHasher;
+use std::collections::HashSet;
+use std::io::BufRead;
+
+// TODO error type
+pub type Result<'i, S, Ix> =
+ std::result::Result<AsgBuilderResult<'i, S, Ix>, Box<dyn Error>>;
+
+pub struct AsgBuilderResult<'i, S, Ix>
+where
+ S: BuildHasher + Default,
+ Ix: IndexType,
+{
+ pub roots: Vec<ObjectRef<Ix>>,
+ pub found: HashSet<&'i str, S>,
+ pub name: Option<&'i Symbol<'i>>,
+ pub relroot: Option<String>,
+}
+
+pub trait AsgBuilder<'i, O, S, Ix>
+where
+ O: IdentObjectState<'i, O>,
+ S: BuildHasher + Default,
+ Ix: IndexType,
+{
+ fn build<G: Asg<'i, O, Ix>>(
+ self,
+ graph: &mut G,
+ first: bool,
+ ) -> Result<'i, S, Ix>;
+}
+
+impl<'i, B, I, O, S, Ix> AsgBuilder<'i, O, S, Ix> for XmloReader<'i, B, I>
+where
+ B: BufRead,
+ I: Interner<'i>,
+ O: IdentObjectState<'i, O>,
+ S: BuildHasher + Default,
+ Ix: IndexType,
+{
+ // TOOD: remove first
+ fn build<G: Asg<'i, O, Ix>>(
+ mut self,
+ graph: &mut G,
+ first: bool,
+ ) -> Result<'i, S, Ix> {
+ // TODO
+ let mut found: HashSet<&'i str, S> = Default::default();
+
+ let mut roots = Vec::new();
+ let mut elig = None;
+
+ let mut name: Option<&'i Symbol<'i>> = None;
+ let mut relroot: Option<String> = None;
+
+ loop {
+ match self.read_event() {
+ Ok(XmloEvent::Package(attrs)) => {
+ if first {
+ name = attrs.name;
+ relroot = attrs.relroot;
+ }
+ elig = attrs.elig;
+ }
+
+ Ok(XmloEvent::SymDeps(sym, deps)) => {
+ // TODO: API needs to expose whether a symbol is already
+ // known so that we can warn on them
+
+ // Maps should not pull in symbols since we may end up
+ // mapping to params that are never actually used
+ if !sym.starts_with(":map:") {
+ for dep_sym in deps {
+ graph.add_dep_lookup(sym, dep_sym);
+ }
+ }
+ }
+
+ Ok(XmloEvent::SymDecl(sym, attrs)) => {
+ if let Some(sym_src) = attrs.src {
+ found.insert(sym_src);
+ } else {
+ let owned = attrs.src.is_none();
+ let extern_ = attrs.extern_;
+
+ let kind = (&attrs).try_into().map_err(|err| {
+ format!("sym `{}` attrs error: {}", sym, err)
+ });
+
+ let mut src: Source = attrs.into();
+
+ // Existing convention is to omit @src of local package
+ // (in this case, the program being linked)
+ if first {
+ src.pkg_name = None;
+ }
+
+ match kind {
+ Ok(kindval) => {
+ // TODO: inefficient
+ let link_root = owned
+ && (kindval == IdentKind::Meta
+ || kindval == IdentKind::Map
+ || kindval == IdentKind::RetMap);
+
+ if extern_ {
+ graph.declare_extern(sym, kindval, src)?;
+ } else {
+ let node =
+ graph.declare(sym, kindval, src)?;
+
+ if link_root {
+ roots.push(node);
+ }
+ }
+ }
+ Err(e) => return Err(e.into()),
+ };
+ }
+ }
+
+ Ok(XmloEvent::Fragment(sym, text)) => {
+ match graph.lookup(sym) {
+ Some(frag) => match graph.set_fragment(frag, text) {
+ Ok(_) => (),
+ Err(e) => return Err(e.into()),
+ },
+ None => {
+ return Err(XmloError::MissingFragment(
+ String::from("missing fragment"),
+ )
+ .into());
+ }
+ };
+ }
+
+ // We don't need to read any further than the end of the
+ // header (symtable, sym-deps, fragments)
+ Ok(XmloEvent::Eoh) => break,
+
+ Err(e) => return Err(e.into()),
+ }
+ }
+
+ if let Some(elig_sym) = elig {
+ roots.push(graph.lookup(elig_sym).expect(
+ "internal error: package elig references nonexistant symbol",
+ ));
+ }
+
+ Ok(AsgBuilderResult {
+ roots,
+ found,
+ name,
+ relroot,
+ })
+ }
+}
diff --git a/tamer/src/obj/xmlo/mod.rs b/tamer/src/obj/xmlo/mod.rs
index 9600792..a30ab7b 100644
--- a/tamer/src/obj/xmlo/mod.rs
+++ b/tamer/src/obj/xmlo/mod.rs
@@ -75,3 +75,6 @@
//! ```
pub mod reader;
+mod asg_builder;
+
+pub use asg_builder::{AsgBuilder, AsgBuilderResult};