Validate constant type preconditions in the LLVMValueRef Create* wrappers - #259
Merged
tannergooding merged 4 commits intoJul 15, 2026
Merged
Conversation
The ConstReal family maps onto ConstantFP::get, which requires a floating-point (or floating-point vector) type. Passing an integer type previously produced corrupt IR (ppc_fp128) or crashed the raw binding. Surface a clear ArgumentException from the safer wrapper instead. Addresses dotnet#194. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
ConstInt maps onto ConstantInt::get via unwrap<IntegerType>, so a non-integer type silently produces corrupt IR (e.g. 'i0 0' for a double) rather than erroring -- the integer-side analogue of the ConstReal issue in dotnet#194. Surface a clear ArgumentException instead. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…get types ConstantExpr::getIntToPtr/getPtrToInt assert the operand and target are int-or-int-vector / ptr-or-ptr-vector respectively; swapping them is an easy footgun that the unchecked bindings pass straight through. Mirror those asserts in the safer wrappers via a shared scalar-type helper. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
… throwers Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #194.
The
LLVMValueRef.Create*helpers are billed as the "safer (but still lowlevel)" wrappers over the raw bindings, but several of the constant creators pass a mistyped operand straight through to libLLVM, where it either silently produces corrupt IR or -- on a releaselibLLVMwith asserts compiled out -- access-violates. #194 is the canonical example:CreateConstRealon ani32reinterpreted the type asppc_fp128on LLVM 14 and hard-crashes on current libLLVM. The module verifier can't cover this, since the raw binding faults before you can verify.This mirrors libLLVM's own C++ asserts in the wrappers so the mistake surfaces as a clear
ArgumentExceptionpointing at the right helper, while the rawLLVM.*bindings stay unchecked by design.CreateConstReal/CreateConstRealOfString/CreateConstRealOfStringAndSizenow require a floating-point (scalar or vector) type, matchingConstantFP::get.CreateConstInt/CreateConstIntOfArbitraryPrecision/CreateConstIntOfString/CreateConstIntOfStringAndSizenow require an integer type, matchingConstantInt::getviaunwrap<IntegerType>. Without this,CreateConstInt(Double, 8)silently returnsi0 0.CreateConstIntToPtr/CreateConstPtrToIntnow require the operand and target to be int-or-int-vector / ptr-or-ptr-vector on the correct sides, matching the asserts inConstantExpr::getIntToPtr/getPtrToInt. Swapping the two is an easy footgun.The checks are factored through a shared
GetScalarTypehelper so scalar and vector types are handled the same way libLLVM does.Intentionally left alone:
CreateConstBitCast-- its contract isCastInst::castIsValid, which isn't a trivial type-kind check, so approximating it would be worse than deferring to the verifier -- and theIRBuilderBuild*surface, which is deliberately lowlevel and covered byVerify/TryVerify.Tests: added
tests/LLVMSharp.UnitTests/Constants.cscovering each guard's reject and accept paths. Full suite is green (2596 passed, 0 warnings).