chsasank / llama.lisp

Lisp dialect designed for HPC and AI
GNU Lesser General Public License v2.1
15 stars 6 forks source link

error: expected instruction opcode . Error received when llvm code was passed to ```bash ../brilisp/run.sh``` when trying to compile a matrix multiplication c-lisp code #38

Closed adi-lb-phoenix closed 4 months ago

adi-lb-phoenix commented 4 months ago

When the output from $ guile ../../utils/sexp-json.scm < matrix_multiplication.sexp | python3 ../../c-lisp.py | python3 ../../brilisp.py | python ../../llvm.py was fed into bash ../brilisp/run.sh , the below shown error was thrown.

$ guile ../../utils/sexp-json.scm < matrix_multiplication.sexp | python3 ../../c-lisp.py | python3 ../../brilisp.py | python ../../llvm.py| bash ../brilisp/run.sh
/tmp/tmp.SxEdPKa4GH.ll:167:1: error: expected instruction opcode
  167 | }
      | ^
1 error generated.
../brilisp/run.sh: line 9: /tmp/tmp.M2Q2136kah.out: Permission denied 

This is the code that was written in c-lisp (matrix_multiplication.sexp) which was given as an input to guile ../../utils/sexp-json.scm

(c-lisp
    (define ((matrix_multiplication void) (xout (ptr float)) (x (ptr float)) (w (ptr float)) (n int) (d int)) 
        (declare (i int))
        (for ( (set i 0) (lt i d) (set i (add i 1)) )
            (declare (val float))
            (set val 0.0)
            (declare (j int))
            (for ((set j 0) (lt j n) (set j (add j 1)))
               (set val (fadd val (fmul (load (ptradd w (add (mul i n) j))) (load (ptradd x j)))))
            )
            (store (ptradd xout i) val)
        ) 
    )
)

This was the input given to bash ../brilisp/run.sh

$ guile ../../utils/sexp-json.scm < matrix_multiplication.sexp | python3 ../../c-lisp.py | python3 ../../brilisp.py | python ../../llvm.py
; ModuleID = ""
target triple = "unknown-unknown-unknown"
target datalayout = ""

define void @"matrix_multiplication"(float* %"xout", float* %"x", float* %"w", i32 %"n", i32 %"d")
{
alloca-hwdeyruq:
  %"xout.1" = alloca float*
  %"x.1" = alloca float*
  %"w.1" = alloca float*
  %"n.1" = alloca i32
  %"d.1" = alloca i32
  %"tmp_clisp-myvvztwi" = alloca i32
  %"i" = alloca i32
  %"tmp_clisp.inp_0-tifpaiid" = alloca i32
  %"tmp_clisp.inp_1-qqagurna" = alloca i32
  %"tmp_clisp.cond-yoeqgrzo" = alloca i1
  %"tmp_clisp-yzjtqbcz" = alloca float
  %"val.twcwjsjw" = alloca float
  %"tmp_clisp-eqmzlcai" = alloca i32
  %"j.twcwjsjw" = alloca i32
  %"tmp_clisp.inp_0-lgfovtpl" = alloca i32
  %"tmp_clisp.inp_1-bguarjjv" = alloca i32
  %"tmp_clisp.cond-prqqdmwu" = alloca i1
  %"tmp_clisp.inp_0-xvbgbjas" = alloca float
  %"tmp_clisp.inp_0-erpemslg" = alloca i32
  %"tmp_clisp.inp_1-szoccafe" = alloca i32
  %"tmp_clisp.inp_0-doqcfdlm" = alloca i32
  %"tmp_clisp.inp_1-edumjpkf" = alloca i32
  %"tmp_clisp-tgleieml" = alloca i32
  %"tmp_clisp-nrujdajx" = alloca float*
  %"tmp_clisp.inp_0-hginnuwd" = alloca float
  %"tmp_clisp-tmtyncui" = alloca i32
  %"tmp_clisp-haukttod" = alloca float*
  %"tmp_clisp.inp_1-ouflrbka" = alloca float
  %"tmp_clisp.inp_1-rkturhmt" = alloca float
  %"tmp_clisp-hovlhhsi" = alloca float
  %"tmp_clisp.inp_0-jkjsczxt" = alloca i32
  %"tmp_clisp.inp_1-juxjtpcq" = alloca i32
  %"tmp_clisp-imybfwyj" = alloca i32
  %"tmp_clisp-cejghyey" = alloca i32
  %"tmp_clisp.ptr-bgtckjbj" = alloca float*
  %"tmp_clisp.val-zhylzszl" = alloca float
  %"tmp_clisp-kgfuitee" = alloca float
  %"tmp_clisp.inp_0-ckkbtnlq" = alloca i32
  %"tmp_clisp.inp_1-kfxbxrxh" = alloca i32
  %"tmp_clisp-rrkrmwxv" = alloca i32
  br label %"entry-ojeudlal"
entry-ojeudlal:
  store float* %"xout", float** %"xout.1"
  store float* %"x", float** %"x.1"
  store float* %"w", float** %"w.1"
  store i32 %"n", i32* %"n.1"
  store i32 %"d", i32* %"d.1"
  store i32 0, i32* %"tmp_clisp-myvvztwi"
  %".13" = load i32, i32* %"tmp_clisp-myvvztwi"
  store i32 %".13", i32* %"i"
  br label %"tmp_clisp.loop-wqclvjzg"
tmp_clisp.loop-wqclvjzg:
  %".16" = load i32, i32* %"i"
  store i32 %".16", i32* %"tmp_clisp.inp_0-tifpaiid"
  %".18" = load i32, i32* %"d.1"
  store i32 %".18", i32* %"tmp_clisp.inp_1-qqagurna"
  %".20" = load i32, i32* %"tmp_clisp.inp_0-tifpaiid"
  %".21" = load i32, i32* %"tmp_clisp.inp_1-qqagurna"
  %"tmp_clisp.cond-yoeqgrzo.1" = icmp slt i32 %".20", %".21"
  store i1 %"tmp_clisp.cond-yoeqgrzo.1", i1* %"tmp_clisp.cond-yoeqgrzo"
  %".23" = load i1, i1* %"tmp_clisp.cond-yoeqgrzo"
  br i1 %".23", label %"tmp_clisp.cont-zllyoxwk", label %"tmp_clisp.break-aphfxdtk"
tmp_clisp.cont-zllyoxwk:
  store float              0x0, float* %"tmp_clisp-yzjtqbcz"
  %".26" = load float, float* %"tmp_clisp-yzjtqbcz"
  store float %".26", float* %"val.twcwjsjw"
  store i32 0, i32* %"tmp_clisp-eqmzlcai"
  %".29" = load i32, i32* %"tmp_clisp-eqmzlcai"
  store i32 %".29", i32* %"j.twcwjsjw"
  br label %"tmp_clisp.loop-mrrebthr"
tmp_clisp.loop-mrrebthr:
  %".32" = load i32, i32* %"j.twcwjsjw"
  store i32 %".32", i32* %"tmp_clisp.inp_0-lgfovtpl"
  %".34" = load i32, i32* %"n.1"
  store i32 %".34", i32* %"tmp_clisp.inp_1-bguarjjv"
  %".36" = load i32, i32* %"tmp_clisp.inp_0-lgfovtpl"
  %".37" = load i32, i32* %"tmp_clisp.inp_1-bguarjjv"
  %"tmp_clisp.cond-prqqdmwu.1" = icmp slt i32 %".36", %".37"
  store i1 %"tmp_clisp.cond-prqqdmwu.1", i1* %"tmp_clisp.cond-prqqdmwu"
  %".39" = load i1, i1* %"tmp_clisp.cond-prqqdmwu"
  br i1 %".39", label %"tmp_clisp.cont-mlgfkxdw", label %"tmp_clisp.break-hbyfzxit"
tmp_clisp.cont-mlgfkxdw:
  %".41" = load float, float* %"val.twcwjsjw"
  store float %".41", float* %"tmp_clisp.inp_0-xvbgbjas"
  %".43" = load i32, i32* %"i"
  store i32 %".43", i32* %"tmp_clisp.inp_0-erpemslg"
  %".45" = load i32, i32* %"n.1"
  store i32 %".45", i32* %"tmp_clisp.inp_1-szoccafe"
  %".47" = load i32, i32* %"tmp_clisp.inp_0-erpemslg"
  %".48" = load i32, i32* %"tmp_clisp.inp_1-szoccafe"
  %"tmp_clisp.inp_0-doqcfdlm.1" = mul i32 %".47", %".48"
  store i32 %"tmp_clisp.inp_0-doqcfdlm.1", i32* %"tmp_clisp.inp_0-doqcfdlm"
  %".50" = load i32, i32* %"j.twcwjsjw"
  store i32 %".50", i32* %"tmp_clisp.inp_1-edumjpkf"
  %".52" = load i32, i32* %"tmp_clisp.inp_0-doqcfdlm"
  %".53" = load i32, i32* %"tmp_clisp.inp_1-edumjpkf"
  %"tmp_clisp-tgleieml.1" = add i32 %".52", %".53"
  store i32 %"tmp_clisp-tgleieml.1", i32* %"tmp_clisp-tgleieml"
  %".55" = load float*, float** %"w.1"
  %".56" = load i32, i32* %"tmp_clisp-tgleieml"
  %".57" = getelementptr float, float* %".55", i32 %".56"
  store float* %".57", float** %"tmp_clisp-nrujdajx"
  %".59" = load float*, float** %"tmp_clisp-nrujdajx"
  %".60" = load float, float* %".59"
  store float %".60", float* %"tmp_clisp.inp_0-hginnuwd"
  %".62" = load i32, i32* %"j.twcwjsjw"
  store i32 %".62", i32* %"tmp_clisp-tmtyncui"
  %".64" = load float*, float** %"x.1"
  %".65" = load i32, i32* %"tmp_clisp-tmtyncui"
  %".66" = getelementptr float, float* %".64", i32 %".65"
  store float* %".66", float** %"tmp_clisp-haukttod"
  %".68" = load float*, float** %"tmp_clisp-haukttod"
  %".69" = load float, float* %".68"
  store float %".69", float* %"tmp_clisp.inp_1-ouflrbka"
  %".71" = load float, float* %"tmp_clisp.inp_0-hginnuwd"
  %".72" = load float, float* %"tmp_clisp.inp_1-ouflrbka"
  %"tmp_clisp.inp_1-rkturhmt.1" = fmul float %".71", %".72"
  store float %"tmp_clisp.inp_1-rkturhmt.1", float* %"tmp_clisp.inp_1-rkturhmt"
  %".74" = load float, float* %"tmp_clisp.inp_0-xvbgbjas"
  %".75" = load float, float* %"tmp_clisp.inp_1-rkturhmt"
  %"tmp_clisp-hovlhhsi.1" = fadd float %".74", %".75"
  store float %"tmp_clisp-hovlhhsi.1", float* %"tmp_clisp-hovlhhsi"
  %".77" = load float, float* %"tmp_clisp-hovlhhsi"
  store float %".77", float* %"val.twcwjsjw"
  %".79" = load i32, i32* %"j.twcwjsjw"
  store i32 %".79", i32* %"tmp_clisp.inp_0-jkjsczxt"
  store i32 1, i32* %"tmp_clisp.inp_1-juxjtpcq"
  %".82" = load i32, i32* %"tmp_clisp.inp_0-jkjsczxt"
  %".83" = load i32, i32* %"tmp_clisp.inp_1-juxjtpcq"
  %"tmp_clisp-imybfwyj.1" = add i32 %".82", %".83"
  store i32 %"tmp_clisp-imybfwyj.1", i32* %"tmp_clisp-imybfwyj"
  %".85" = load i32, i32* %"tmp_clisp-imybfwyj"
  store i32 %".85", i32* %"j.twcwjsjw"
  br label %"tmp_clisp.loop-mrrebthr"
tmp_clisp.break-hbyfzxit:
  %".88" = load i32, i32* %"i"
  store i32 %".88", i32* %"tmp_clisp-cejghyey"
  %".90" = load float*, float** %"xout.1"
  %".91" = load i32, i32* %"tmp_clisp-cejghyey"
  %".92" = getelementptr float, float* %".90", i32 %".91"
  store float* %".92", float** %"tmp_clisp.ptr-bgtckjbj"
  %".94" = load float, float* %"val.twcwjsjw"
  store float %".94", float* %"tmp_clisp.val-zhylzszl"
  %".96" = load float*, float** %"tmp_clisp.ptr-bgtckjbj"
  %".97" = load float, float* %"tmp_clisp.val-zhylzszl"
  store float %".97", float* %".96"
  %".99" = load float, float* %"tmp_clisp.val-zhylzszl"
  store float %".99", float* %"tmp_clisp-kgfuitee"
  %".101" = load i32, i32* %"i"
  store i32 %".101", i32* %"tmp_clisp.inp_0-ckkbtnlq"
  store i32 1, i32* %"tmp_clisp.inp_1-kfxbxrxh"
  %".104" = load i32, i32* %"tmp_clisp.inp_0-ckkbtnlq"
  %".105" = load i32, i32* %"tmp_clisp.inp_1-kfxbxrxh"
  %"tmp_clisp-rrkrmwxv.1" = add i32 %".104", %".105"
  store i32 %"tmp_clisp-rrkrmwxv.1", i32* %"tmp_clisp-rrkrmwxv"
  %".107" = load i32, i32* %"tmp_clisp-rrkrmwxv"
  store i32 %".107", i32* %"i"
  br label %"tmp_clisp.loop-wqclvjzg"
tmp_clisp.break-aphfxdtk:
}
chsasank commented 4 months ago

@GlowingScrewdriver: this seems to happen when only thing in a function body is a for loop. break label in for will not have any instructions then.

GlowingScrewdriver commented 4 months ago

This is related to #31. The easiest way to work around this is by inserting a return statement outside the for loop, at the end of the function

chsasank commented 4 months ago

I don't think is really about implicit returns. It's about having empty label when there's no statement following a for. We can very much have return inside the for and still have this error.

GlowingScrewdriver commented 4 months ago

Alright, perhaps implicit returns is not the correct word. The main problem here is an unterminated basic block.

The issue here is an unterminated basic block. My solution would be to use LLVM's unreachable instruction to mark an empty BB as terminated.

chsasank commented 4 months ago

Look at how C's LLVM code generator deals with this and adopt that solution.

GlowingScrewdriver commented 4 months ago

Okay, Clang's approach is pretty smart. There is one variable dedicated to holding the return value of a function. When a C return statement appears, the return variable is assigned, and control jumps to the last basic block. The last basic block contains an LLVM ret instruction that returns the return variable.

Makes a lot of sense. I'll refactor C-Lisp to do it this way.