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:
@@ -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)))
|
||||
Reference in New Issue
Block a user