Initial draft of DSL semantics complete.

This latest refactor adds "extractor macros" in place of the
very-confusing-even-to-the-DSL-author reverse-rules-as-extractors
concept. It was beautifully symmetric but also just too mind-bending to
be practical.

It also adds argument polarity to external extractors. This is inspired
by Prolog's similar notion (see e.g. the "+x" vs. "-x" argument notation
in library documentation) where the unification-based semantics allow
for bidirectional flow through arguments. We don't want polymorphism
or dynamism w.r.t. directions/polarities here; the polarities are
static; but it is useful to be able to feed values *into* an extractor
(aside from the one value being extracted). Semantically this still
correlates to a term-rewriting/value-equivalence world since we can
still translate all of this to a list of equality constraints.

To make that work, this change also adds expressions into patterns,
specifically only for extractor "input" args. This required quite a bit
of internal refactoring but is only a small addition to the language
semantics.

I plan to build out the little instruction-selector sketch further but
the one that is here (in `test3.isle`) is starting to get interesting
already with the current DSL semantics.
This commit is contained in:
Chris Fallin
2021-09-09 00:48:36 -07:00
parent 1ceef04680
commit 6daa55af82
10 changed files with 970 additions and 672 deletions

View File

@@ -5,29 +5,29 @@
Store))
(type Inst (primitive Inst))
(type InstInput (primitive InstInput))
(type Reg (primitive Reg))
(type u32 (primitive u32))
(decl Op (Opcode) Inst)
(extractor Op get_opcode)
(extern extractor Op get_opcode)
(decl InputToReg (Inst u32) Reg)
(constructor InputToReg put_input_in_reg)
(decl InstInput (InstInput u32) Inst)
(extern extractor InstInput get_inst_input (out in))
(decl Producer (Inst) InstInput)
(extern extractor Producer get_input_producer)
(decl UseInput (InstInput) Reg)
(extern constructor UseInput put_input_in_reg)
(type MachInst (enum
(Add (a Reg) (b Reg))
(Add3 (a Reg) (b Reg) (c Reg))
(Sub (a Reg) (b Reg))))
(decl Lower (Inst) MachInst)
;; These can be made nicer by defining some extractors -- see below.
(rule
(Lower inst @ (Op (Opcode.Iadd)))
(MachInst.Add (InputToReg inst 0) (InputToReg inst 1)))
(rule
(Lower inst @ (Op (Opcode.Isub)))
(MachInst.Sub (InputToReg inst 0) (InputToReg inst 1)))
;; Extractors that give syntax sugar for (Iadd ra rb), etc.
;;
;; Note that this is somewhat simplistic: it directly connects inputs to
@@ -39,19 +39,28 @@
;; we are dealing (at the semantic level) with pure value equivalences of
;; "terms", not arbitrary side-effecting calls.
(decl Iadd (Reg Reg) Inst)
(decl Isub (Reg Reg) Inst)
(rule
inst @ (Op Opcode.Iadd)
(Iadd (InputToReg inst 0) (InputToReg inst 1)))
(rule
inst @ (Op Opcode.Isub)
(Isub (InputToReg inst 0) (InputToReg inst 1)))
(decl Iadd (InstInput InstInput) Inst)
(decl Isub (InstInput InstInput) Inst)
(extractor
(Iadd a b)
(and
(Op (Opcode.Iadd))
(InstInput a <0)
(InstInput b <1)))
(extractor
(Isub a b)
(and
(Op (Opcode.Isub))
(InstInput a <0)
(InstInput b <1)))
;; Now the nice syntax-sugar that "end-user" backend authors can write:
(rule
(Lower (Iadd ra rb))
(MachInst.Add ra rb))
(Lower (Iadd ra rb))
(MachInst.Add (UseInput ra) (UseInput rb)))
(rule
(Lower (Isub ra rb))
(MachInst.Sub ra rb))
(Lower (Iadd (Producer (Iadd ra rb)) rc))
(MachInst.Add3 (UseInput ra) (UseInput rb) (UseInput rc)))
(rule
(Lower (Isub ra rb))
(MachInst.Sub (UseInput ra) (UseInput rb)))