-
Notifications
You must be signed in to change notification settings - Fork 16
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
Subtly incorrect logic in Text.LLVM.call
?
#144
Comments
Thanks for the report. As noted in our README, LLVM instructions and syntax can change with different versions, and indeed this seems to have been a change that started in LLVM 14 and was finalized in LLVM17. I embedded your sample in the following test harness (targeting my local machine's triple, although that's just for {-# LANGUAGE OverloadedStrings #-}
import qualified Text.LLVM as L
import qualified Text.LLVM.Triple.AST as L3
import qualified Text.LLVM.PP as LP
import Data.Int
import Text.Read ( readMaybe )
import System.Environment ( getArgs )
mod1 :: L.LLVM (L.Typed L.Value)
mod1 = do
printf <- L.declare (L.iT 32) "printf" [L.ptrT (L.iT 8)] True
fmtStr <- L.string "d_fmt" "%lf\n\0"
L.define L.emptyFunAttrs (L.iT 32) "main" () $ do
_ <- L.call printf [fmtStr, doubleT L.-: L.toValue (pi :: Double)]
L.ret (L.iT 32 L.-: (0 :: Int32))
doubleT :: L.Type
doubleT = L.PrimType $ L.FloatType L.Double
main = do args <- getArgs
let llvmver = if length args < 1
then LP.llvmVlatest
else case (readMaybe $ args !! 0) :: Maybe Int of
Just n -> n
Nothing -> LP.llvmVlatest
let tgtTriple = L3.TargetTriple
{
L3.ttArch = L3.X86_64
, L3.ttSubArch = mempty
, L3.ttVendor = L3.PC
, L3.ttOS = L3.Linux
, L3.ttEnv = L3.GNU
, L3.ttObjFmt = L3.ELF
}
let llvmMod = (snd $ L.runLLVM mod1) { L.modTriple = tgtTriple }
-- putStrLn $ show llvmMod
putStrLn $ "---- for LLVM " <> show llvmver
let ll = show $ LP.ppLLVM llvmver $ LP.llvmPP llvmMod
-- putStrLn ll
writeFile "calltest.ll" ll
putStrLn "wrote calltest.ll" This matches your first form (no trailing
If I then modify the code to remove the trailing
And indeed, in https://releases.llvm.org/17.0.1/docs/LangRef.html#call-instruction the examples dropped the I suspect that the removal of the pointer indirection for function types corresponds to the shift to Opaque Pointers in LLVM, where pointers no longer carry type information (https://llvm.org/devmtg/2022-04-03/slides/keynote.Opaque.Pointers.Are.Coming.pdf). At this point, I think the right path forward is to update the type returned by For the moment, if you are targeting LLVM 17 (or potentially LLVM 15+), you can use your |
Yeah for my use case I'm most definitely happy to just run with I'm sorry this sent you down some very deep rabbit hole, but am very thankful for the detailed exploration.
Yeah the fact that "the right (LLVM) type" is dependent on the LLVM version is quite messed up. But it also seems tricky to just hand the problem over to all users either (including future me who may have forgotten about this in 6 months), as many will likely not know about those changes. For what it's worth, my personal preference probably goes to allowing the library be a bit closer to "what the user thinks and means" when it comes to codegen. Most of the time we're just declaring, defining and calling things, so I'd probably be happy if the library could be made a bit more flexible so as to easily encode what I want while retaining all the info it needs to pretty-print the right incantation later, once the LLVM version is known. (The first solution sounds to me like it may be a bit too confusing for users. "What do you mean I need to give the LLVM version to this function, in the middle of the codegen logic?") |
I disagree that we need to do something differently based on the LLVM version here. Rather, I think using #include <stdio.h>
int main(void) {
printf("%d\n", 42);
return 0;
} Then you'll get something that looks like:
Note that
Therefore, I think the inclusion of the extra pointer type in the list of examples in https://releases.llvm.org/14.0.0/docs/LangRef.html#call-instruction was simply an oversight (that has since been fixed). As such, I think we should just remove the trailing |
The documentation shows the |
Patch in #145 - review/feedback welcome :) |
make pretty-printing of call consistent with LLVM's expectations (#144)
Fixed in #145. |
Hello,
First off, thanks a lot for this package.
I stumbled upon some odd behaviour (possibly related to #102 (comment) ?). When I try to call a function that I either
declare
d ordefine
d in the sameLLVM
monad computation, using theText.LLVM.call
function, the function type is printed with an excessive pointer, see below.This results in:
Notice the
*
at the end ofi32(i8*, ...)*
, which shouldn't be there.This IR, when executed with
lli
:If I edit the IR manually to remove that extra pointer in the type, and try to run again:
I tracked down the issue to the definition of
call
:If I instead define and use the following function in place of
Text.LLVM.call
:then I get the correct IR (the one in
test2.ll
) and some digits ofpi
get printed, like withtest2.ll
.Am I somehow misusing
define
/declare
/call
or shouldcall
be patched?Cheers
The text was updated successfully, but these errors were encountered: