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

How are values larger than u64 handled for Constant::Int? #5

Open
phi-go opened this issue Sep 24, 2020 · 3 comments
Open

How are values larger than u64 handled for Constant::Int? #5

phi-go opened this issue Sep 24, 2020 · 3 comments

Comments

@phi-go
Copy link

phi-go commented Sep 24, 2020

Hey,

first of all thank you for this lib, it is very nice to work with!

I noticed that llvm can have int values of arbitrary size, one example mentions an integer with the size of more than a million bits. In the case that raised this question for me, I have a constant integer size of 128, in a normally compiled program. However, the actual value fits inside a u64 and is used as part of the mul instruction.
https://releases.llvm.org/10.0.0/docs/LangRef.html#integer-type

The internal field value that contains the constant value is of size u64.

value: u64, // If the Int is less than 64 bits, the value will be zero-extended to create the Rust `u64` `value` (so if `bits` is 8, the lowest 8 bits of `value` are the relevant bits, and the others are all zeroes). Note that LLVM integers aren't signed or unsigned; each individual instruction indicates whether it's treating the integer as signed or unsigned if necessary (e.g., UDiv vs SDiv).

So my question is, what happens for a constant int value that is larger than a u64?

@cdisselkoen
Copy link
Owner

A great question, thanks for reporting!

Currently, llvm-ir relies on the LLVM C API function LLVMConstIntGetZExtValue(), which in turn calls the C++ function llvm::ConstantInt::getZExtValue(), which fails with assert() if the constant value doesn't fit in 64 bits. (Larger constants are fine if they have all zeroes in the bits higher than 64.) So, to answer the "what happens" question, I believe that if your 128-bit constant integer has all zeroes in the upper 64 bits (so, if it is less than 2^64) then the value in the Constant::Int represents the true 128-bit constant value; but if the 128-bit constant integer doesn't fit in 64 bits, then Module::from_bc_path() will fail.

I may be missing something, but it looks to me at first glance that the LLVM C API doesn't have a function to get the values of larger constant integers. This may be part of the same family of problems discussed in our README in the Limitations section (see also LLVM bug 42692). If that is indeed the case, then the fix here will have to be to submit a patch to LLVM adding a function or functions to the LLVM C API. On first glace, I think the C API function should probably use llvm::ConstantInt::getValue() and then somehow expose the resulting llvm::APInt over the C interface. If you're interested in working on this, by all means go for it!

@phi-go
Copy link
Author

phi-go commented Sep 25, 2020

Thank you for the fast and comprehensive answer!
For my use case this is actually a reasonable state of things.

If my project, that I'm using this library for, works out, I will probably take some time to look at removing some limitations.
However, until then I can't promise that I will find time to do so.

I guess we should leave this issue open, until someone gets around to it.

@cdisselkoen
Copy link
Owner

I'm happy leaving this open until someone gets around to it (doesn't have to be you). I might make a note in our Limitations section or in the Constant docs. Thanks for the report!

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

2 participants