Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Other Examples #2

Open
sdiehl opened this issue Jan 18, 2017 · 19 comments
Open

Other Examples #2

sdiehl opened this issue Jan 18, 2017 · 19 comments

Comments

@sdiehl
Copy link
Member

sdiehl commented Jan 18, 2017

Any ideas on what other simple use case examples I should make for the bindings. Was thinking about some of these:

  • Read and writing IR, Bytecode from disk.
  • Optimizer pass customization
  • libffi integration
  • Target customization
@cocreature
Copy link
Member

cocreature commented Jan 18, 2017

The last three seem to me like they are the most interesting and useful ones, probably in the order you listed them.

@ckoparkar
Copy link

ckoparkar commented Jan 29, 2017

I'm pretty new to llvm-hs, and llvm in general and this may sound dumb compared to the other ideas. But can you please help me by posting an example which generates printf ? I've been having a tough time using GetElementPtr to convert the char array to a pointer, and generate printf("%d", 42).

Also, what do you guys think about having a gitter channel ? Or a mailing list perhaps ? @sdiehl, thanks for the blog-post! It helped me a lot. But other than that, there aren't many resources available I guess. I mean, besides the Hackage documentation.

@ckoparkar
Copy link

I found a workaround, sort of. I'm just creating a "library" of functions like print_int, print_string etc, and using that when compiling my IR. Is this the best way to do this ?

@cocreature
Copy link
Member

@cskksc One easy way to figure out how something is represented in LLVM is to take a look at the output of clang -flto -S. You can then use withModuleFromLLVMAssembly context <string representation of module> moduleAST to get the llvm-hs ast from that and print it to see how it looks.

A simplified example of this output can be seen in https://gist.github.com/cocreature/93625b5afac68eb7de8b2eaa44561ab6. This works fine if you just want to generate LLVM IR. You need to link against glibc to be able to actually run this. In JITed code you need to make sure that the symbol resolvers are able to find the printf symbol in your current process (since Haskell executables link against glibc I think it should already be available). I don’t remember the exact steps needed for that.

@ckoparkar
Copy link

ckoparkar commented Jan 29, 2017

@cocreature Thanks a lot! Right now I'm just generating the IR file and compiling it by hand using clang. So I was successfully able to run a toy print_int program, generated with llvm-hs. I was stuck on generating the IR for printing strings. But this helps a lot. And using withModuleFromLLVMAssembly is neat. That should help me figure out some other things too. Thanks again :-)

@sdiehl
Copy link
Member Author

sdiehl commented Jan 29, 2017

I'll make an example for compiling variadic functions like printf. It's a little tricky with LLVM and probably worthy of an example.

@ckoparkar
Copy link

@sdiehl Thanks!

@ghost
Copy link

ghost commented Feb 20, 2018

It would be great to have an example of conditional branch where a symbol table is also kept. I am confused how to use the recursive do with StateT wrapped around IRBuilder.

@sdiehl
Copy link
Member Author

sdiehl commented Feb 20, 2018

Ok, I'll add some more IRBuilder examples. I was planning on just rewriting the Kaleidoscope tutorial to use it which should hit all the features.

@ghost
Copy link

ghost commented Feb 22, 2018

Thanks, as a matter of fact I am working through the Kaleidoscope tutorial. What I am stuck at is how to keep environment, for example in entry block there is a new variable, and you want to refer to it in the if/else blocks. I looked at StateT, but it has no instance of MonadFix.

@cocreature
Copy link
Member

@pavolzetor I don’t quite understand what problem you are running into, maybe you just need a phi node? Could you provide an example of the code you are trying to generate? Also StateT does have a MonadFix instance.

@sdiehl
Copy link
Member Author

sdiehl commented Feb 22, 2018

@cocreature This is actually an issue I'm hitting as well, I might need to add a function to forward declare references to blocks. The cbr requires us to create two blocks enter one, and then add instructions to the second one after finishing the first. This doesn't fit naturally into the IRBuilder model currently.

https://github.com/sdiehl/kaleidoscope/blob/master/src/chapter7/Emit.hs#L122

@cocreature
Copy link
Member

@sdiehl Sorry I still don’t get it, why does the following example not work for your usecase? I feel like I’m missing something obvious here :)

simple :: Module
simple = buildModule "exampleModule" $ mdo
  function "f" [(AST.i32, "a")] AST.i32 $ \[a] -> mdo
    entry <- block `named` "entry"
    cond <- icmp P.EQ a (ConstantOperand (C.Int 32 0))
    condBr cond ifThen ifElse
    ifThen <- block
    trVal <- add a (ConstantOperand (C.Int 32 0))
    br ifExit
    ifElse <- block `named` "if.else"
    flVal <- add a (ConstantOperand (C.Int 32 0))
    br ifElse
    ifExit <- block `named` "if.exit"
    r <- phi [(trVal, ifThen), (flVal, ifElse)]
    ret r

@ghost
Copy link

ghost commented Feb 23, 2018

@cocreature it should be ifExit. I can't find MonadFix instance in Foundation.Monad.State. Anyhow, here is a simple example that I do not know how to handle using IRBuilder.

int
main(void)
{
        int x = 10;
        if (x)
                x = 1;
        else
                x = 2;
        return x;
}

Code from Clang:

define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store i32 10, i32* %2, align 4
  %3 = load i32, i32* %2, align 4
  %4 = icmp ne i32 %3, 0
  br i1 %4, label %5, label %6

; <label>:5:                                      ; preds = %0
  store i32 1, i32* %2, align 4
  br label %7

; <label>:6:                                      ; preds = %0
  store i32 2, i32* %2, align 4
  br label %7

; <label>:7:                                      ; preds = %6, %5
  %8 = load i32, i32* %2, align 4
  ret i32 %8
}

The issue I am having is that I want to populate environment with declarations as I go and refer to them using that environment.

@sdiehl
Copy link
Member Author

sdiehl commented Feb 23, 2018

I can't find MonadFix instance in Foundation.Monad.State.

If you're using an alternative prelude that doesn't include MonadFix then this is the issue. You should request this upstream in Foundation in you need it.

@cocreature
Copy link
Member

Until foundation adds the MonadFix instance you could also just be using StateT from transformers. Ofc the interface to that might deviate from the one in foundation but I doubt the differences are particularly large.

@ghost
Copy link

ghost commented Feb 25, 2018

Thanks, that worked. I reported the issue and will think if there is a better way to solve the problem then rely on mdo, especially for back edges.

Here is a link to a subset of kaleidoscope https://github.com/pavolzetor/kaleidoscope-compiler. I may add custom operators and JIT later.

@cocreature
Copy link
Member

will think if there is a better way to solve the problem then rely on mdo, especially for back edges.

What exactly is bothering you about mdo? IMHO this is pretty much the perfect usecase for MonadFix. While I completely agree that understanding MonadFix can be a bit tricky, ime using it generally tends to be quite straightforward and minus the occasional infinite loop it just works™.

@ghost
Copy link

ghost commented Feb 28, 2018

Higher bar for beginners. I agree using MonadFix is elegant in this case and I need to study it more.

In general, if a feature is not that commonly used, it is very important to document the tought process so it is clear why it is necessary/useful. It took me while to understand why it was useful in this particular case :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants