ISLE: Common accessors for some insn data fields (#3781)

Add accessors to prelude.isle to access data fields of
`func_addr` and `symbol_value` instructions.

These are based on similar versions I had added to the s390x
back-end, but are a bit more straightforward to use.

- func_ref_data: Extract SigRef, ExternalName, and RelocDistance
  fields given a FuncRef.

- symbol_value_data: Extract ExternalName, RelocDistance, and
  offset fields given a GlobalValue representing a Symbol.

- reloc_distance_near: Test for RelocDistance::Near.

The s390x back-end is changed to use these common versions.

Note that this exposed a bug in common isle code: This extractor:

(extractor (load_sym inst)
  (and inst
       (load _ (def_inst (symbol_value
                           (symbol_value_data _
                             (reloc_distance_near) offset)))
               (i64_from_offset
                 (memarg_symbol_offset_sum <offset _)))))

would raise an assertion in sema.rs due to a supposed cycle in
extractor definitions.  But there was no actual cycle, it was
simply that the extractor tree refers twice to the `insn_data`
extractor (once via the `load` and once via the `symbol_value`
extractor).  Fixed by checking for pre-existing definitions only
along one path in the tree, not across the whole tree.
This commit is contained in:
Ulrich Weigand
2022-02-09 02:57:27 +01:00
committed by GitHub
parent 9c5c872b3b
commit 10198553c7
13 changed files with 960 additions and 883 deletions

View File

@@ -1034,21 +1034,19 @@ impl TermEnv {
}
// Check for cycles in the extractor call graph.
let mut seen = BTreeSet::new();
let mut stack = vec![];
'outer: for root in extractor_call_graph.keys().copied() {
seen.clear();
stack.clear();
stack.push((root, vec![root]));
stack.push((root, vec![root], BTreeSet::new()));
while let Some((caller, path)) = stack.pop() {
while let Some((caller, path, mut seen)) = stack.pop() {
let is_new = seen.insert(caller);
if is_new {
if let Some(callees) = extractor_call_graph.get(&caller) {
stack.extend(callees.iter().map(|callee| {
let mut path = path.clone();
path.push(*callee);
(*callee, path)
(*callee, path, seen.clone())
}));
}
} else {