cisen / blog

Time waits for no one.
133 stars 20 forks source link

isle #1155

Open cisen opened 1 year ago

cisen commented 1 year ago

https://github.com/cisen/sourcecode-isle

总结

// decl 函数名 参数类型列表 返回结果列表
(decl produces_flags_append (ProducesFlags MInst) ProducesFlags)
// 转换为一个提供一个这样的函数:x是变量,如果输入x为-1,则得到返回结果-2
(rule (X -1) -2)

翻译对照

0

(type i64 (primitive i64))

(decl X (i64) i64)
// 转换为一个提供一个这样的函数:x是变量,如果输入x为-1,则得到返回结果-2
(rule (X -1) -2)
(rule (X -2) -3)
(rule (X 0x7fff_ffff_ffff_ffff) 0x8000_0000_0000_0000)
(rule (X 0xffff_ffff_ffff_fff0) 1)

(type i128 (primitive i128))

(decl Y (i128) i128)

(rule (Y 0x1000_0000_0000_0000_1234_5678_9abc_def0) -1)
(rule (Y 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff) 3)

(rule (Y -0x1000_0000_0000_0000_1234_5678_9abc_def0) 1)
(rule (Y -0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff) -3)

翻译结果

// GENERATED BY ISLE. DO NOT EDIT!
//
// Generated automatically from the instruction-selection DSL code in:
// - cranelift/isle/isle/isle_examples/run/iconst.isle

#![allow(dead_code, unreachable_code, unreachable_patterns)]
#![allow(unused_imports, unused_variables, non_snake_case, unused_mut)]
#![allow(irrefutable_let_patterns, unused_assignments, non_camel_case_types)]

use super::*;  // Pulls in all external types.
use std::marker::PhantomData;

/// Context during lowering: an implementation of this trait
/// must be provided with all external constructors and extractors.
/// A mutable borrow is passed along through all lowering logic.
pub trait Context {
}

           pub trait ContextIter {
               type Context;
               type Output;
               fn next(&mut self, ctx: &mut Self::Context) -> Option<Self::Output>;
           }

           pub struct ContextIterWrapper<Item, I: Iterator < Item = Item>, C: Context> {
               iter: I,
               _ctx: PhantomData<C>,
           }
           impl<Item, I: Iterator<Item = Item>, C: Context> From<I> for ContextIterWrapper<Item, I, C> {
               fn from(iter: I) -> Self {
                   Self { iter, _ctx: PhantomData }
               }
           }
           impl<Item, I: Iterator<Item = Item>, C: Context> ContextIter for ContextIterWrapper<Item, I, C> {
               type Context = C;
               type Output = Item;
               fn next(&mut self, _ctx: &mut Self::Context) -> Option<Self::Output> {
                   self.iter.next()
               }
           }

// Generated as internal constructor for term X.
pub fn constructor_X<C: Context>(ctx: &mut C, arg0: i64) -> Option<i64> {
    let pattern0_0 = arg0;
    if pattern0_0 == -2i128 as i64  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 5.
        let expr0_0: i64 = -3i128 as i64;
        return Some(expr0_0);
    }
    if pattern0_0 == -1i128 as i64  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 4.
        let expr0_0: i64 = -2i128 as i64;
        return Some(expr0_0);
    }
    if pattern0_0 == 9223372036854775807i128 as i64  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 6.
        let expr0_0: i64 = 9223372036854775808i128 as i64;
        return Some(expr0_0);
    }
    if pattern0_0 == 18446744073709551600i128 as i64  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 7.
        let expr0_0: i64 = 1i128 as i64;
        return Some(expr0_0);
    }
    return None;
}

// Generated as internal constructor for term Y.
pub fn constructor_Y<C: Context>(ctx: &mut C, arg0: i128) -> Option<i128> {
    let pattern0_0 = arg0;
    if pattern0_0 == -21267647932558653967772681431949303536i128  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 16.
        let expr0_0: i128 = 1i128;
        return Some(expr0_0);
    }
    // 为什么这里是1?因为0 - fffffff = 1
    if pattern0_0 == -1i128  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 14.
        let expr0_0: i128 = 3i128;
        return Some(expr0_0);
    }
    if pattern0_0 == 1i128  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 17.
        let expr0_0: i128 = -3i128;
        return Some(expr0_0);
    }
    if pattern0_0 == 21267647932558653967772681431949303536i128  {
        // Rule at cranelift/isle/isle/isle_examples/run/iconst.isle line 13.
        let expr0_0: i128 = -1i128;
        return Some(expr0_0);
    }
    return None;
}

提供给用户调用

mod iconst;

struct Context;
impl iconst::Context for Context {}

fn main() {
    let mut ctx = Context;

    assert_eq!(iconst::constructor_X(&mut ctx, -1), Some(-2));
    assert_eq!(iconst::constructor_X(&mut ctx, -2), Some(-3));
    assert_eq!(iconst::constructor_X(&mut ctx, 0x7fff_ffff_ffff_ffff), Some(0x8000_0000_0000_0000u64 as i64));
    assert_eq!(iconst::constructor_X(&mut ctx, 0xffff_ffff_ffff_fff0_u64 as i64), Some(1));

    assert_eq!(iconst::constructor_Y(&mut ctx, 0x1000_0000_0000_0000_1234_5678_9abc_def0), Some(-1));
    assert_eq!(iconst::constructor_Y(&mut ctx, 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffffu128 as i128), Some(3));
    assert_eq!(iconst::constructor_Y(&mut ctx, -0x1000_0000_0000_0000_1234_5678_9abc_def0), Some(1));
    assert_eq!(iconst::constructor_Y(&mut ctx, -(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffffu128 as i128)), Some(-3));
}

1

(type SideEffectNoResult (enum
      (Inst (inst MInst))
      (Inst2 (inst1 MInst)
             (inst2 MInst))
      (Inst3 (inst1 MInst)
             (inst2 MInst)
             (inst3 MInst))))
/// Internal type SideEffectNoResult: defined at src\prelude.isle line 639.
#[derive(Clone, Debug)]
pub enum SideEffectNoResult {
    Inst {
        inst: MInst,
    },
    Inst2 {
        inst1: MInst,
        inst2: MInst,
    },
    Inst3 {
        inst1: MInst,
        inst2: MInst,
        inst3: MInst,
    },
}

2

;; Construct a single-element `InstOutput` from a single register.
(decl output_reg (Reg) InstOutput)
(rule (output_reg reg) (output (value_reg reg)))
// Generated as internal constructor for term output_reg.
pub fn constructor_output_reg<C: Context>(ctx: &mut C, arg0: Reg) -> Option<InstOutput> {
    let pattern0_0 = arg0;
    // Rule at src\prelude.isle line 121.
    let expr0_0 = C::value_reg(ctx, pattern0_0);
    let expr1_0 = C::output(ctx, expr0_0);
    return Some(expr1_0);
}

3 if else

;; Chain another producer to a `ProducesFlags`.
(decl produces_flags_append (ProducesFlags MInst) ProducesFlags)
(rule (produces_flags_append (ProducesFlags.ProducesFlagsSideEffect inst1) inst2)
      (ProducesFlags.ProducesFlagsTwiceSideEffect inst1 inst2))
// Generated as internal constructor for term produces_flags_append.
pub fn constructor_produces_flags_append<C: Context>(
    ctx: &mut C,
    arg0: &ProducesFlags,
    arg1: &MInst,
) -> Option<ProducesFlags> {
    let pattern0_0 = arg0;
    if let &ProducesFlags::ProducesFlagsSideEffect {
        inst: ref pattern1_0,
    } = pattern0_0
    {
        let pattern2_0 = arg1;
        // Rule at src\prelude.isle line 693.
        let expr0_0 = ProducesFlags::ProducesFlagsTwiceSideEffect {
            inst1: pattern1_0.clone(),
            inst2: pattern2_0.clone(),
        };
        return Some(expr0_0);
    }
    return None;
}

4 match

;; Modify a ProducesFlags to use it only for its side-effect, ignoring
;; its result.
(decl produces_flags_ignore (ProducesFlags) ProducesFlags)
(rule (produces_flags_ignore (ProducesFlags.ProducesFlagsReturnsReg inst _))
      (ProducesFlags.ProducesFlagsSideEffect inst))
(rule (produces_flags_ignore (ProducesFlags.ProducesFlagsReturnsResultWithConsumer inst _))
      (ProducesFlags.ProducesFlagsSideEffect inst))
// Generated as internal constructor for term produces_flags_ignore.
pub fn constructor_produces_flags_ignore<C: Context>(
    ctx: &mut C,
    arg0: &ProducesFlags,
) -> Option<ProducesFlags> {
    let pattern0_0 = arg0;
    match pattern0_0 {
        &ProducesFlags::ProducesFlagsReturnsReg {
            inst: ref pattern1_0,
            result: pattern1_1,
        } => {
            // Rule at src\prelude.isle line 723.
            let expr0_0 = ProducesFlags::ProducesFlagsSideEffect {
                inst: pattern1_0.clone(),
            };
            return Some(expr0_0);
        }
        &ProducesFlags::ProducesFlagsReturnsResultWithConsumer {
            inst: ref pattern1_0,
            result: pattern1_1,
        } => {
            // Rule at src\prelude.isle line 725.
            let expr0_0 = ProducesFlags::ProducesFlagsSideEffect {
                inst: pattern1_0.clone(),
            };
            return Some(expr0_0);
        }
        _ => {}
    }
    return None;
}

5 嵌套

(convert u8 u64 u8_as_u64)
(decl lower_clz (Type Reg) Reg)
(rule
  (lower_clz ty rs)
  (if-let $false (has_b))
  (gen_cltz $true rs ty))
(rule 2
  (lower_clz $I64 r)
  (if-let $true (has_b))
  (alu_rr_funct12 (AluOPRRI.Clz) r))
(rule 2
  (lower_clz $I32 r)
  (if-let $true (has_b))
  (alu_rr_funct12 (AluOPRRI.Clzw) r))

;;; for I8 and I16
(rule 1
  (lower_clz ty r)
  (if-let $true (has_b))
  (let
    ( ;; narrow int make all upper bits are zeros.
      (tmp Reg (ext_int_if_need $false r ty ))
      ;; 
      (count Reg (alu_rr_funct12 (AluOPRRI.Clz) tmp))
      ;;make result
      (result Reg (alu_rr_imm12 (AluOPRRI.Addi) count (imm12_const_add (ty_bits ty) -64))))
    result))
// Generated as internal constructor for term lower_clz.
pub fn constructor_lower_clz<C: Context>(ctx: &mut C, arg0: Type, arg1: Reg) -> Option<Reg> {
    let pattern0_0 = arg0;
    if pattern0_0 == I32 {
        let pattern2_0 = arg1;
        let mut closure3 = || {
            let expr0_0 = C::has_b(ctx)?;
            return Some(expr0_0);
        };
        if let Some(pattern3_0) = closure3() {
            if pattern3_0 == true {
                // Rule at src\isa\riscv64\inst.isle line 963.
                let expr0_0 = AluOPRRI::Clzw;
                let expr1_0 = constructor_alu_rr_funct12(ctx, &expr0_0, pattern2_0)?;
                return Some(expr1_0);
            }
        }
    }
    if pattern0_0 == I64 {
        let pattern2_0 = arg1;
        let mut closure3 = || {
            let expr0_0 = C::has_b(ctx)?;
            return Some(expr0_0);
        };
        if let Some(pattern3_0) = closure3() {
            if pattern3_0 == true {
                // Rule at src\isa\riscv64\inst.isle line 959.
                let expr0_0 = AluOPRRI::Clz;
                let expr1_0 = constructor_alu_rr_funct12(ctx, &expr0_0, pattern2_0)?;
                return Some(expr1_0);
            }
        }
    }
    let pattern0_0 = arg0;
    let pattern1_0 = arg1;
    let mut closure2 = || {
        let expr0_0 = C::has_b(ctx)?;
        return Some(expr0_0);
    };
    if let Some(pattern2_0) = closure2() {
        if pattern2_0 == true {
            // Rule at src\isa\riscv64\inst.isle line 969.
            let expr0_0: bool = false;
            let expr1_0 = C::value_reg(ctx, pattern1_0);
            let expr2_0 = constructor_ext_int_if_need(ctx, expr0_0, expr1_0, pattern0_0)?;
            let expr3_0 = constructor_convert_valueregs_reg(ctx, expr2_0)?;
            let expr4_0 = AluOPRRI::Clz;
            let expr5_0 = constructor_alu_rr_funct12(ctx, &expr4_0, expr3_0)?;
            let expr6_0 = AluOPRRI::Addi;
            let expr7_0 = C::ty_bits(ctx, pattern0_0)?;
            let expr8_0 = C::u8_as_i32(ctx, expr7_0);
            let expr9_0: i32 = -64i128 as i32;
            let expr10_0 = C::imm12_const_add(ctx, expr8_0, expr9_0);
            let expr11_0 = constructor_alu_rr_imm12(ctx, &expr6_0, expr5_0, expr10_0)?;
            return Some(expr11_0);
        }
    }
    let pattern0_0 = arg0;
    let pattern1_0 = arg1;
    let mut closure2 = || {
        let expr0_0 = C::has_b(ctx)?;
        return Some(expr0_0);
    };
    if let Some(pattern2_0) = closure2() {
        if pattern2_0 == false {
            // Rule at src\isa\riscv64\inst.isle line 956.
            let expr0_0: bool = true;
            let expr1_0 = constructor_gen_cltz(ctx, expr0_0, pattern1_0, pattern0_0)?;
            return Some(expr1_0);
        }
    }
    return None;
}