From 57edc8339ee31cdd9c73185b272807c37134fa99 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 14:34:05 -0700 Subject: [PATCH 01/11] Add native libLLVMSharp helpers for C++ API surface absent from the C-API Add CallBase, CmpInst, GlobalValue, Instruction, Type, and Value helpers that mirror LLVM C++ methods the LLVM-C API does not expose, and remove the now-unused Instruction hasNoSignedWrap/hasNoUnsignedWrap helpers superseded by LLVMGetNSW/GetNUW. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 120 ++++++++++++++++++++++++++++- sources/libLLVMSharp/LLVMSharp.h | 38 ++++++++- 2 files changed, 152 insertions(+), 6 deletions(-) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 5e6c4504..75e0ad8d 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -13,13 +13,17 @@ #include #include #include +#include #include +#include #include #include #include #include #include +#include #include +#include #include #include #include @@ -38,6 +42,56 @@ DEFINE_ISA_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) // Implementation code +uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call) +{ + CallBase* unwrapped = unwrap(call); + return unwrapped->isIndirectCall() ? 1 : 0; +} + +int32_t llvmsharp_CmpInst_getInversePredicate(LLVMValueRef instruction) +{ + CmpInst* unwrapped = unwrap(instruction); + return (int32_t)unwrapped->getInversePredicate(); +} + +const char* llvmsharp_CmpInst_getPredicateName(LLVMValueRef instruction, int32_t* out_size) +{ + CmpInst* unwrapped = unwrap(instruction); + StringRef name = CmpInst::getPredicateName(unwrapped->getPredicate()); + *out_size = (int32_t)name.size(); + return name.data(); +} + +int32_t llvmsharp_CmpInst_getSwappedPredicate(LLVMValueRef instruction) +{ + CmpInst* unwrapped = unwrap(instruction); + return (int32_t)unwrapped->getSwappedPredicate(); +} + +uint8_t llvmsharp_CmpInst_isFalseWhenEqual(LLVMValueRef instruction) +{ + CmpInst* unwrapped = unwrap(instruction); + return unwrapped->isFalseWhenEqual() ? 1 : 0; +} + +uint8_t llvmsharp_CmpInst_isSigned(LLVMValueRef instruction) +{ + CmpInst* unwrapped = unwrap(instruction); + return unwrapped->isSigned() ? 1 : 0; +} + +uint8_t llvmsharp_CmpInst_isTrueWhenEqual(LLVMValueRef instruction) +{ + CmpInst* unwrapped = unwrap(instruction); + return unwrapped->isTrueWhenEqual() ? 1 : 0; +} + +uint8_t llvmsharp_CmpInst_isUnsigned(LLVMValueRef instruction) +{ + CmpInst* unwrapped = unwrap(instruction); + return unwrapped->isUnsigned() ? 1 : 0; +} + const char* llvmsharp_ConstantDataArray_getData(LLVMValueRef array, int32_t* out_size) { ConstantDataArray* unwrapped = unwrap(array); @@ -337,6 +391,18 @@ LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function) return wrap(type); } +uint32_t llvmsharp_GlobalValue_getAddressSpace(LLVMValueRef global_value) +{ + GlobalValue* unwrapped = unwrap(global_value); + return unwrapped->getAddressSpace(); +} + +uint8_t llvmsharp_GlobalValue_isDSOLocal(LLVMValueRef global_value) +{ + GlobalValue* unwrapped = unwrap(global_value); + return unwrapped->isDSOLocal() ? 1 : 0; +} + LLVMMetadataRef llvmsharp_GlobalVariable_getGlobalVariableExpression(LLVMValueRef global_variable) { LLVMMetadataRef unwrapped = llvmsharp_GlobalVariable_getMetadata(global_variable, LLVMContext::MD_dbg); @@ -356,16 +422,36 @@ LLVMMetadataRef llvmsharp_GlobalVariable_getMetadata(LLVMValueRef global_variabl return wrap(unwrapped->getMetadata(KindID)); } -uint8_t llvmsharp_Instruction_hasNoSignedWrap(LLVMValueRef instruction) +const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size) +{ + Instruction* unwrapped = unwrap(instruction); + const char* name = unwrapped->getOpcodeName(); + *out_size = (int32_t)strlen(name); + return name; +} + +uint8_t llvmsharp_Instruction_isCommutative(LLVMValueRef instruction) +{ + Instruction* unwrapped = unwrap(instruction); + return unwrapped->isCommutative() ? 1 : 0; +} + +uint8_t llvmsharp_Instruction_mayHaveSideEffects(LLVMValueRef instruction) +{ + Instruction* unwrapped = unwrap(instruction); + return unwrapped->mayHaveSideEffects() ? 1 : 0; +} + +uint8_t llvmsharp_Instruction_mayReadFromMemory(LLVMValueRef instruction) { Instruction* unwrapped = unwrap(instruction); - return unwrapped->hasNoSignedWrap() ? 1 : 0; + return unwrapped->mayReadFromMemory() ? 1 : 0; } -uint8_t llvmsharp_Instruction_hasNoUnsignedWrap(LLVMValueRef instruction) +uint8_t llvmsharp_Instruction_mayWriteToMemory(LLVMValueRef instruction) { Instruction* unwrapped = unwrap(instruction); - return unwrapped->hasNoUnsignedWrap() ? 1 : 0; + return unwrapped->mayWriteToMemory() ? 1 : 0; } uint32_t llvmsharp_MDNode_getNumOperands(LLVMMetadataRef metadata) @@ -429,6 +515,32 @@ void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass unwrap(pass_manager)->add(unwrap(pass)); } +uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable) +{ + Type* unwrapped = unwrap(type); + TypeSize size = unwrapped->getPrimitiveSizeInBits(); + *out_isScalable = size.isScalable() ? 1 : 0; + return size.getKnownMinValue(); +} + +uint32_t llvmsharp_Type_getScalarSizeInBits(LLVMTypeRef type) +{ + Type* unwrapped = unwrap(type); + return unwrapped->getScalarSizeInBits(); +} + +uint32_t llvmsharp_Value_getNumUses(LLVMValueRef value) +{ + Value* unwrapped = unwrap(value); + return (uint32_t)unwrapped->getNumUses(); +} + +LLVMValueRef llvmsharp_Value_stripPointerCasts(LLVMValueRef value) +{ + Value* unwrapped = unwrap(value); + return wrap(unwrapped->stripPointerCasts()); +} + LLVMPassRef llvmsharp_createDeadCodeEliminationPass() { return wrap((Pass*)createDeadCodeEliminationPass()); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 30032a1b..16c29bba 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -78,6 +78,22 @@ LLVM_CLANG_C_EXTERN_C_BEGIN // Function declarations +LLVMSHARP_LINKAGE uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call); + +LLVMSHARP_LINKAGE int32_t llvmsharp_CmpInst_getInversePredicate(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE const char* llvmsharp_CmpInst_getPredicateName(LLVMValueRef instruction, int32_t* out_size); + +LLVMSHARP_LINKAGE int32_t llvmsharp_CmpInst_getSwappedPredicate(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isFalseWhenEqual(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isSigned(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isTrueWhenEqual(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isUnsigned(LLVMValueRef instruction); + LLVMSHARP_LINKAGE const char* llvmsharp_ConstantDataArray_getData(LLVMValueRef array, int32_t* out_size); LLVMSHARP_LINKAGE uint32_t llvmsharp_DIBasicType_getEncoding(LLVMMetadataRef type); @@ -152,13 +168,23 @@ LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getFunctionType(LLVMValueRef fu LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function); +LLVMSHARP_LINKAGE uint32_t llvmsharp_GlobalValue_getAddressSpace(LLVMValueRef global_value); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_GlobalValue_isDSOLocal(LLVMValueRef global_value); + LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_GlobalVariable_getGlobalVariableExpression(LLVMValueRef global_variable); LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_GlobalVariable_getMetadata(LLVMValueRef global_variable, uint32_t KindID); -LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_hasNoSignedWrap(LLVMValueRef instruction); +LLVMSHARP_LINKAGE const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_isCommutative(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayHaveSideEffects(LLVMValueRef instruction); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayReadFromMemory(LLVMValueRef instruction); -LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_hasNoUnsignedWrap(LLVMValueRef instruction); +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayWriteToMemory(LLVMValueRef instruction); LLVMSHARP_LINKAGE uint32_t llvmsharp_MDNode_getNumOperands(LLVMMetadataRef metadata); @@ -176,6 +202,14 @@ LLVMSHARP_LINKAGE void llvmsharp_Module_GetIdentifiedStructTypes(LLVMModuleRef m LLVMSHARP_LINKAGE void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass); +LLVMSHARP_LINKAGE uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable); + +LLVMSHARP_LINKAGE uint32_t llvmsharp_Type_getScalarSizeInBits(LLVMTypeRef type); + +LLVMSHARP_LINKAGE uint32_t llvmsharp_Value_getNumUses(LLVMValueRef value); + +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Value_stripPointerCasts(LLVMValueRef value); + LLVMSHARP_LINKAGE LLVMPassRef llvmsharp_createDeadCodeEliminationPass(); LLVMSHARP_LINKAGE LLVMPassRef llvmsharp_createSROAPass(uint8_t PreserveCFG); From 5fbba8bf169166b2d4b594c24d27ae22f4c9c739 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 18:41:59 -0700 Subject: [PATCH 02/11] Expose a JITLink object-linking-layer creator via libLLVMSharp Add llvmsharp_OrcCreateObjectLinkingLayer, returning an LLVMOrcObjectLayerRef backed by llvm::orc::ObjectLinkingLayer for use with LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator, so the JIT can run object linking on JITLink instead of RuntimeDyld. Link LLVMOrcJIT and LLVMJITLink to resolve the ObjectLinkingLayer C++ symbols. Resolves #263 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/CMakeLists.txt | 2 ++ sources/libLLVMSharp/LLVMSharp.cpp | 14 ++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 3 +++ 3 files changed, 19 insertions(+) diff --git a/sources/libLLVMSharp/CMakeLists.txt b/sources/libLLVMSharp/CMakeLists.txt index e171ffa6..5e49104c 100644 --- a/sources/libLLVMSharp/CMakeLists.txt +++ b/sources/libLLVMSharp/CMakeLists.txt @@ -34,7 +34,9 @@ target_link_libraries(LLVMSharp PRIVATE LLVMCFGuard) target_link_libraries(LLVMSharp PRIVATE LLVMInstCombine) target_link_libraries(LLVMSharp PRIVATE LLVMInstrumentation) target_link_libraries(LLVMSharp PRIVATE LLVMipo) +target_link_libraries(LLVMSharp PRIVATE LLVMJITLink) target_link_libraries(LLVMSharp PRIVATE LLVMObjCARCOpts) +target_link_libraries(LLVMSharp PRIVATE LLVMOrcJIT) target_link_libraries(LLVMSharp PRIVATE LLVMScalarOpts) target_link_libraries(LLVMSharp PRIVATE LLVMTransformUtils) target_link_libraries(LLVMSharp PRIVATE LLVMVectorize) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 75e0ad8d..11746974 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -9,6 +9,9 @@ #endif // Library includes (<> instead of "") +#include +#include +#include #include #include #include @@ -19,8 +22,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -39,6 +44,8 @@ using namespace llvm; // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_ISA_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ExecutionSession, LLVMOrcExecutionSessionRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ObjectLayer, LLVMOrcObjectLayerRef) // Implementation code @@ -510,6 +517,13 @@ void llvmsharp_Module_GetIdentifiedStructTypes(LLVMModuleRef module, LLVMTypeRef *out_size = (int32_t)types.size(); } +LLVMOrcObjectLayerRef llvmsharp_OrcCreateObjectLinkingLayer(LLVMOrcExecutionSessionRef execution_session) +{ + orc::ExecutionSession* unwrapped = unwrap(execution_session); + orc::ObjectLinkingLayer* layer = new orc::ObjectLinkingLayer(*unwrapped); + return wrap(static_cast(layer)); +} + void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass) { unwrap(pass_manager)->add(unwrap(pass)); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 16c29bba..02f5c5c2 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -10,6 +10,7 @@ // Include headers #include +#include #include #ifdef _MSC_VER @@ -200,6 +201,8 @@ LLVM_FOR_EACH_METADATA_SUBCLASS(LLVMSHARP_METADATA_ISA) LLVMSHARP_LINKAGE void llvmsharp_Module_GetIdentifiedStructTypes(LLVMModuleRef module, LLVMTypeRef** out_buffer, int32_t* out_size); +LLVMSHARP_LINKAGE LLVMOrcObjectLayerRef llvmsharp_OrcCreateObjectLinkingLayer(LLVMOrcExecutionSessionRef execution_session); + LLVMSHARP_LINKAGE void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass); LLVMSHARP_LINKAGE uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable); From bccc6dad3ed4c14a9c7d2b4060e378ba6e79021a Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 18:56:42 -0700 Subject: [PATCH 03/11] Add native constant-folding and instruction-simplification helpers Expose ConstantFoldInstruction, ConstantFoldConstant, ConstantFoldCompareInstOperands, and simplifyInstruction from LLVMAnalysis, which the LLVM-C API does not surface. The opcode-based ConstantFoldBinaryOpOperands/ConstantFoldCastOperand folders are deferred since the internal Instruction opcode numbering does not match the C LLVMOpcode enum. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/CMakeLists.txt | 1 + sources/libLLVMSharp/LLVMSharp.cpp | 31 +++++++++++++++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 8 ++++++++ 3 files changed, 40 insertions(+) diff --git a/sources/libLLVMSharp/CMakeLists.txt b/sources/libLLVMSharp/CMakeLists.txt index 5e49104c..99686d05 100644 --- a/sources/libLLVMSharp/CMakeLists.txt +++ b/sources/libLLVMSharp/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries(LLVMSharp PRIVATE LLVM-C) target_link_libraries(LLVMSharp PRIVATE LLVMDemangle) target_link_libraries(LLVMSharp PRIVATE LLVMAggressiveInstCombine) +target_link_libraries(LLVMSharp PRIVATE LLVMAnalysis) target_link_libraries(LLVMSharp PRIVATE LLVMCFGuard) target_link_libraries(LLVMSharp PRIVATE LLVMInstCombine) target_link_libraries(LLVMSharp PRIVATE LLVMInstrumentation) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 11746974..96821924 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -9,6 +9,8 @@ #endif // Library includes (<> instead of "") +#include +#include #include #include #include @@ -107,6 +109,28 @@ const char* llvmsharp_ConstantDataArray_getData(LLVMValueRef array, int32_t* out return stringRef.data(); } +LLVMValueRef llvmsharp_ConstantFoldCompareInstOperands(int32_t predicate, LLVMValueRef lhs, LLVMValueRef rhs, LLVMModuleRef module) +{ + Constant* lhsConstant = unwrap(lhs); + Constant* rhsConstant = unwrap(rhs); + const DataLayout& dataLayout = unwrap(module)->getDataLayout(); + return wrap(ConstantFoldCompareInstOperands((unsigned)predicate, lhsConstant, rhsConstant, dataLayout)); +} + +LLVMValueRef llvmsharp_ConstantFoldConstant(LLVMValueRef constant, LLVMModuleRef module) +{ + Constant* unwrapped = unwrap(constant); + const DataLayout& dataLayout = unwrap(module)->getDataLayout(); + return wrap(ConstantFoldConstant(unwrapped, dataLayout)); +} + +LLVMValueRef llvmsharp_ConstantFoldInstruction(LLVMValueRef instruction, LLVMModuleRef module) +{ + Instruction* unwrapped = unwrap(instruction); + const DataLayout& dataLayout = unwrap(module)->getDataLayout(); + return wrap(ConstantFoldInstruction(unwrapped, dataLayout)); +} + uint32_t llvmsharp_DIBasicType_getEncoding(LLVMMetadataRef type) { DIBasicType* unwrapped = unwrap(type); @@ -529,6 +553,13 @@ void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass unwrap(pass_manager)->add(unwrap(pass)); } +LLVMValueRef llvmsharp_simplifyInstruction(LLVMValueRef instruction, LLVMModuleRef module) +{ + Instruction* unwrapped = unwrap(instruction); + const DataLayout& dataLayout = unwrap(module)->getDataLayout(); + return wrap(simplifyInstruction(unwrapped, SimplifyQuery(dataLayout))); +} + uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable) { Type* unwrapped = unwrap(type); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 02f5c5c2..37fdd7d6 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -97,6 +97,12 @@ LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isUnsigned(LLVMValueRef instruction) LLVMSHARP_LINKAGE const char* llvmsharp_ConstantDataArray_getData(LLVMValueRef array, int32_t* out_size); +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_ConstantFoldCompareInstOperands(int32_t predicate, LLVMValueRef lhs, LLVMValueRef rhs, LLVMModuleRef module); + +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_ConstantFoldConstant(LLVMValueRef constant, LLVMModuleRef module); + +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_ConstantFoldInstruction(LLVMValueRef instruction, LLVMModuleRef module); + LLVMSHARP_LINKAGE uint32_t llvmsharp_DIBasicType_getEncoding(LLVMMetadataRef type); LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_DICompositeType_getBaseType(LLVMMetadataRef type); @@ -205,6 +211,8 @@ LLVMSHARP_LINKAGE LLVMOrcObjectLayerRef llvmsharp_OrcCreateObjectLinkingLayer(LL LLVMSHARP_LINKAGE void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass); +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_simplifyInstruction(LLVMValueRef instruction, LLVMModuleRef module); + LLVMSHARP_LINKAGE uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable); LLVMSHARP_LINKAGE uint32_t llvmsharp_Type_getScalarSizeInBits(LLVMTypeRef type); From 1dcf5884e385b4f074838668b6942c85dcdb1498 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:00:03 -0700 Subject: [PATCH 04/11] Add native dominator-tree and loop-info analysis helpers Expose DominatorTree, PostDominatorTree, LoopInfo, and Loop from LLVMAnalysis behind opaque handles with explicit create/dispose lifetimes, none of which the LLVM-C API surfaces. Loop handles returned by LoopInfo are non-owning and valid for the lifetime of the owning LoopInfo. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 134 +++++++++++++++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 45 ++++++++++ 2 files changed, 179 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 96821924..0189957f 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -11,12 +11,15 @@ // Library includes (<> instead of "") #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -48,6 +51,10 @@ using namespace llvm; DEFINE_ISA_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ExecutionSession, LLVMOrcExecutionSessionRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ObjectLayer, LLVMOrcObjectLayerRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DominatorTree, LLVMSharpDominatorTreeRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Loop, LLVMSharpLoopRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LoopInfo, LLVMSharpLoopInfoRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PostDominatorTree, LLVMSharpPostDominatorTreeRef) // Implementation code @@ -408,6 +415,51 @@ LLVMMetadataRef llvmsharp_DIVariable_getType(LLVMMetadataRef variable) return wrap(unwrapped->getType()); } +LLVMSharpDominatorTreeRef llvmsharp_DominatorTree_create(LLVMValueRef function) +{ + Function* unwrapped = unwrap(function); + return wrap(new DominatorTree(*unwrapped)); +} + +void llvmsharp_DominatorTree_dispose(LLVMSharpDominatorTreeRef dominator_tree) +{ + delete unwrap(dominator_tree); +} + +uint8_t llvmsharp_DominatorTree_dominatesBlock(LLVMSharpDominatorTreeRef dominator_tree, LLVMBasicBlockRef a, LLVMBasicBlockRef b) +{ + DominatorTree* unwrapped = unwrap(dominator_tree); + return unwrapped->dominates(unwrap(a), unwrap(b)) ? 1 : 0; +} + +uint8_t llvmsharp_DominatorTree_dominatesInstruction(LLVMSharpDominatorTreeRef dominator_tree, LLVMValueRef def, LLVMValueRef user) +{ + DominatorTree* unwrapped = unwrap(dominator_tree); + return unwrapped->dominates(unwrap(def), unwrap(user)) ? 1 : 0; +} + +LLVMBasicBlockRef llvmsharp_DominatorTree_getIDom(LLVMSharpDominatorTreeRef dominator_tree, LLVMBasicBlockRef block) +{ + DominatorTree* unwrapped = unwrap(dominator_tree); + DomTreeNode* node = unwrapped->getNode(unwrap(block)); + if (node == nullptr) + { + return nullptr; + } + DomTreeNode* immediateDominator = node->getIDom(); + if (immediateDominator == nullptr) + { + return nullptr; + } + return wrap(immediateDominator->getBlock()); +} + +uint8_t llvmsharp_DominatorTree_properlyDominatesBlock(LLVMSharpDominatorTreeRef dominator_tree, LLVMBasicBlockRef a, LLVMBasicBlockRef b) +{ + DominatorTree* unwrapped = unwrap(dominator_tree); + return unwrapped->properlyDominates(unwrap(a), unwrap(b)) ? 1 : 0; +} + LLVMTypeRef llvmsharp_Function_getFunctionType(LLVMValueRef function) { Function* unwrapped = unwrap(function); @@ -485,6 +537,71 @@ uint8_t llvmsharp_Instruction_mayWriteToMemory(LLVMValueRef instruction) return unwrapped->mayWriteToMemory() ? 1 : 0; } +LLVMSharpLoopInfoRef llvmsharp_LoopInfo_create(LLVMSharpDominatorTreeRef dominator_tree) +{ + DominatorTree* unwrapped = unwrap(dominator_tree); + return wrap(new LoopInfo(*unwrapped)); +} + +void llvmsharp_LoopInfo_dispose(LLVMSharpLoopInfoRef loop_info) +{ + delete unwrap(loop_info); +} + +uint32_t llvmsharp_LoopInfo_getLoopDepth(LLVMSharpLoopInfoRef loop_info, LLVMBasicBlockRef block) +{ + LoopInfo* unwrapped = unwrap(loop_info); + return unwrapped->getLoopDepth(unwrap(block)); +} + +LLVMSharpLoopRef llvmsharp_LoopInfo_getLoopFor(LLVMSharpLoopInfoRef loop_info, LLVMBasicBlockRef block) +{ + LoopInfo* unwrapped = unwrap(loop_info); + return wrap(unwrapped->getLoopFor(unwrap(block))); +} + +uint8_t llvmsharp_Loop_containsBlock(LLVMSharpLoopRef loop, LLVMBasicBlockRef block) +{ + Loop* unwrapped = unwrap(loop); + return unwrapped->contains(unwrap(block)) ? 1 : 0; +} + +LLVMBasicBlockRef llvmsharp_Loop_getExitBlock(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getExitBlock()); +} + +LLVMBasicBlockRef llvmsharp_Loop_getHeader(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getHeader()); +} + +uint32_t llvmsharp_Loop_getLoopDepth(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return unwrapped->getLoopDepth(); +} + +LLVMBasicBlockRef llvmsharp_Loop_getLoopLatch(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getLoopLatch()); +} + +LLVMBasicBlockRef llvmsharp_Loop_getLoopPreheader(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getLoopPreheader()); +} + +LLVMSharpLoopRef llvmsharp_Loop_getParentLoop(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getParentLoop()); +} + uint32_t llvmsharp_MDNode_getNumOperands(LLVMMetadataRef metadata) { MDNode* unwrapped = unwrap(metadata); @@ -553,6 +670,23 @@ void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass unwrap(pass_manager)->add(unwrap(pass)); } +LLVMSharpPostDominatorTreeRef llvmsharp_PostDominatorTree_create(LLVMValueRef function) +{ + Function* unwrapped = unwrap(function); + return wrap(new PostDominatorTree(*unwrapped)); +} + +void llvmsharp_PostDominatorTree_dispose(LLVMSharpPostDominatorTreeRef post_dominator_tree) +{ + delete unwrap(post_dominator_tree); +} + +uint8_t llvmsharp_PostDominatorTree_dominatesBlock(LLVMSharpPostDominatorTreeRef post_dominator_tree, LLVMBasicBlockRef a, LLVMBasicBlockRef b) +{ + PostDominatorTree* unwrapped = unwrap(post_dominator_tree); + return unwrapped->dominates(unwrap(a), unwrap(b)) ? 1 : 0; +} + LLVMValueRef llvmsharp_simplifyInstruction(LLVMValueRef instruction, LLVMModuleRef module) { Instruction* unwrapped = unwrap(instruction); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 37fdd7d6..84163055 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -71,6 +71,11 @@ */ typedef struct LLVMOpaquePass* LLVMPassRef; +typedef struct LLVMSharpOpaqueDominatorTree* LLVMSharpDominatorTreeRef; +typedef struct LLVMSharpOpaqueLoop* LLVMSharpLoopRef; +typedef struct LLVMSharpOpaqueLoopInfo* LLVMSharpLoopInfoRef; +typedef struct LLVMSharpOpaquePostDominatorTree* LLVMSharpPostDominatorTreeRef; + // Enum definitions // Struct definitions @@ -171,6 +176,18 @@ LLVMSHARP_LINKAGE const char* llvmsharp_DIVariable_getName(LLVMMetadataRef varia LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_DIVariable_getType(LLVMMetadataRef variable); +LLVMSHARP_LINKAGE LLVMSharpDominatorTreeRef llvmsharp_DominatorTree_create(LLVMValueRef function); + +LLVMSHARP_LINKAGE void llvmsharp_DominatorTree_dispose(LLVMSharpDominatorTreeRef dominator_tree); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_DominatorTree_dominatesBlock(LLVMSharpDominatorTreeRef dominator_tree, LLVMBasicBlockRef a, LLVMBasicBlockRef b); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_DominatorTree_dominatesInstruction(LLVMSharpDominatorTreeRef dominator_tree, LLVMValueRef def, LLVMValueRef user); + +LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_DominatorTree_getIDom(LLVMSharpDominatorTreeRef dominator_tree, LLVMBasicBlockRef block); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_DominatorTree_properlyDominatesBlock(LLVMSharpDominatorTreeRef dominator_tree, LLVMBasicBlockRef a, LLVMBasicBlockRef b); + LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getFunctionType(LLVMValueRef function); LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function); @@ -193,6 +210,28 @@ LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayReadFromMemory(LLVMValueRef i LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayWriteToMemory(LLVMValueRef instruction); +LLVMSHARP_LINKAGE LLVMSharpLoopInfoRef llvmsharp_LoopInfo_create(LLVMSharpDominatorTreeRef dominator_tree); + +LLVMSHARP_LINKAGE void llvmsharp_LoopInfo_dispose(LLVMSharpLoopInfoRef loop_info); + +LLVMSHARP_LINKAGE uint32_t llvmsharp_LoopInfo_getLoopDepth(LLVMSharpLoopInfoRef loop_info, LLVMBasicBlockRef block); + +LLVMSHARP_LINKAGE LLVMSharpLoopRef llvmsharp_LoopInfo_getLoopFor(LLVMSharpLoopInfoRef loop_info, LLVMBasicBlockRef block); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Loop_containsBlock(LLVMSharpLoopRef loop, LLVMBasicBlockRef block); + +LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getExitBlock(LLVMSharpLoopRef loop); + +LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getHeader(LLVMSharpLoopRef loop); + +LLVMSHARP_LINKAGE uint32_t llvmsharp_Loop_getLoopDepth(LLVMSharpLoopRef loop); + +LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getLoopLatch(LLVMSharpLoopRef loop); + +LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getLoopPreheader(LLVMSharpLoopRef loop); + +LLVMSHARP_LINKAGE LLVMSharpLoopRef llvmsharp_Loop_getParentLoop(LLVMSharpLoopRef loop); + LLVMSHARP_LINKAGE uint32_t llvmsharp_MDNode_getNumOperands(LLVMMetadataRef metadata); LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_MDNode_getOperand(LLVMMetadataRef metadata, uint32_t index); @@ -211,6 +250,12 @@ LLVMSHARP_LINKAGE LLVMOrcObjectLayerRef llvmsharp_OrcCreateObjectLinkingLayer(LL LLVMSHARP_LINKAGE void llvmsharp_PassManager_add(LLVMPassManagerRef pass_manager, LLVMPassRef pass); +LLVMSHARP_LINKAGE LLVMSharpPostDominatorTreeRef llvmsharp_PostDominatorTree_create(LLVMValueRef function); + +LLVMSHARP_LINKAGE void llvmsharp_PostDominatorTree_dispose(LLVMSharpPostDominatorTreeRef post_dominator_tree); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_PostDominatorTree_dominatesBlock(LLVMSharpPostDominatorTreeRef post_dominator_tree, LLVMBasicBlockRef a, LLVMBasicBlockRef b); + LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_simplifyInstruction(LLVMValueRef instruction, LLVMModuleRef module); LLVMSHARP_LINKAGE uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable); From 5b78b4bd190cc8f6b55d6e06951aaabc00b99705 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:01:48 -0700 Subject: [PATCH 05/11] Add native TargetTransformInfo cost-model helpers Expose a TargetTransformInfo derived from a TargetMachine and Function behind an opaque handle, along with getInstructionCost, getNumberOfRegisters, and getRegisterBitWidth, which the LLVM-C API does not surface. Requires a local DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, ...) since LLVM keeps its own in the non-public TargetMachineC.cpp. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 43 ++++++++++++++++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 12 +++++++++ 2 files changed, 55 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 0189957f..427dc4dc 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +57,8 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DominatorTree, LLVMSharpDominatorTreeRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Loop, LLVMSharpLoopRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LoopInfo, LLVMSharpLoopInfoRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PostDominatorTree, LLVMSharpPostDominatorTreeRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetTransformInfo, LLVMSharpTargetTransformInfoRef) // Implementation code @@ -694,6 +698,45 @@ LLVMValueRef llvmsharp_simplifyInstruction(LLVMValueRef instruction, LLVMModuleR return wrap(simplifyInstruction(unwrapped, SimplifyQuery(dataLayout))); } +LLVMSharpTargetTransformInfoRef llvmsharp_TargetTransformInfo_create(LLVMTargetMachineRef target_machine, LLVMValueRef function) +{ + TargetMachine* targetMachine = unwrap(target_machine); + Function* unwrapped = unwrap(function); + return wrap(new TargetTransformInfo(targetMachine->getTargetTransformInfo(*unwrapped))); +} + +void llvmsharp_TargetTransformInfo_dispose(LLVMSharpTargetTransformInfoRef target_transform_info) +{ + delete unwrap(target_transform_info); +} + +uint8_t llvmsharp_TargetTransformInfo_getInstructionCost(LLVMSharpTargetTransformInfoRef target_transform_info, LLVMValueRef user, int32_t cost_kind, int64_t* out_cost) +{ + TargetTransformInfo* unwrapped = unwrap(target_transform_info); + InstructionCost cost = unwrapped->getInstructionCost(unwrap(user), (TargetTransformInfo::TargetCostKind)cost_kind); + if (!cost.isValid()) + { + *out_cost = 0; + return 0; + } + *out_cost = cost.getValue(); + return 1; +} + +uint32_t llvmsharp_TargetTransformInfo_getNumberOfRegisters(LLVMSharpTargetTransformInfoRef target_transform_info, uint32_t class_id) +{ + TargetTransformInfo* unwrapped = unwrap(target_transform_info); + return unwrapped->getNumberOfRegisters(class_id); +} + +uint32_t llvmsharp_TargetTransformInfo_getRegisterBitWidth(LLVMSharpTargetTransformInfoRef target_transform_info, int32_t register_kind, uint8_t* out_isScalable) +{ + TargetTransformInfo* unwrapped = unwrap(target_transform_info); + TypeSize size = unwrapped->getRegisterBitWidth((TargetTransformInfo::RegisterKind)register_kind); + *out_isScalable = size.isScalable() ? 1 : 0; + return (uint32_t)size.getKnownMinValue(); +} + uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable) { Type* unwrapped = unwrap(type); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 84163055..b63d7d56 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -11,6 +11,7 @@ // Include headers #include #include +#include #include #ifdef _MSC_VER @@ -75,6 +76,7 @@ typedef struct LLVMSharpOpaqueDominatorTree* LLVMSharpDominatorTreeRef; typedef struct LLVMSharpOpaqueLoop* LLVMSharpLoopRef; typedef struct LLVMSharpOpaqueLoopInfo* LLVMSharpLoopInfoRef; typedef struct LLVMSharpOpaquePostDominatorTree* LLVMSharpPostDominatorTreeRef; +typedef struct LLVMSharpOpaqueTargetTransformInfo* LLVMSharpTargetTransformInfoRef; // Enum definitions @@ -258,6 +260,16 @@ LLVMSHARP_LINKAGE uint8_t llvmsharp_PostDominatorTree_dominatesBlock(LLVMSharpPo LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_simplifyInstruction(LLVMValueRef instruction, LLVMModuleRef module); +LLVMSHARP_LINKAGE LLVMSharpTargetTransformInfoRef llvmsharp_TargetTransformInfo_create(LLVMTargetMachineRef target_machine, LLVMValueRef function); + +LLVMSHARP_LINKAGE void llvmsharp_TargetTransformInfo_dispose(LLVMSharpTargetTransformInfoRef target_transform_info); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_TargetTransformInfo_getInstructionCost(LLVMSharpTargetTransformInfoRef target_transform_info, LLVMValueRef user, int32_t cost_kind, int64_t* out_cost); + +LLVMSHARP_LINKAGE uint32_t llvmsharp_TargetTransformInfo_getNumberOfRegisters(LLVMSharpTargetTransformInfoRef target_transform_info, uint32_t class_id); + +LLVMSHARP_LINKAGE uint32_t llvmsharp_TargetTransformInfo_getRegisterBitWidth(LLVMSharpTargetTransformInfoRef target_transform_info, int32_t register_kind, uint8_t* out_isScalable); + LLVMSHARP_LINKAGE uint64_t llvmsharp_Type_getPrimitiveSizeInBits(LLVMTypeRef type, uint8_t* out_isScalable); LLVMSHARP_LINKAGE uint32_t llvmsharp_Type_getScalarSizeInBits(LLVMTypeRef type); From afbca6e9caf69c532983b4b7a6f2d7de46329d26 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:03:16 -0700 Subject: [PATCH 06/11] Add native function cloning and inlining helpers Expose CloneFunction and InlineFunction from LLVMTransformUtils, which the LLVM-C API does not surface. InlineFunction returns whether the inline succeeded. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 16 ++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 427dc4dc..84f42f5f 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #ifdef _MSC_VER @@ -68,6 +69,13 @@ uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call) return unwrapped->isIndirectCall() ? 1 : 0; } +LLVMValueRef llvmsharp_CloneFunction(LLVMValueRef function) +{ + Function* unwrapped = unwrap(function); + ValueToValueMapTy valueMap; + return wrap(CloneFunction(unwrapped, valueMap)); +} + int32_t llvmsharp_CmpInst_getInversePredicate(LLVMValueRef instruction) { CmpInst* unwrapped = unwrap(instruction); @@ -509,6 +517,14 @@ LLVMMetadataRef llvmsharp_GlobalVariable_getMetadata(LLVMValueRef global_variabl return wrap(unwrapped->getMetadata(KindID)); } +uint8_t llvmsharp_InlineFunction(LLVMValueRef call_base) +{ + CallBase* unwrapped = unwrap(call_base); + InlineFunctionInfo inlineFunctionInfo; + InlineResult result = InlineFunction(*unwrapped, inlineFunctionInfo); + return result.isSuccess() ? 1 : 0; +} + const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size) { Instruction* unwrapped = unwrap(instruction); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index b63d7d56..494fa0bb 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -88,6 +88,8 @@ LLVM_CLANG_C_EXTERN_C_BEGIN LLVMSHARP_LINKAGE uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call); +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_CloneFunction(LLVMValueRef function); + LLVMSHARP_LINKAGE int32_t llvmsharp_CmpInst_getInversePredicate(LLVMValueRef instruction); LLVMSHARP_LINKAGE const char* llvmsharp_CmpInst_getPredicateName(LLVMValueRef instruction, int32_t* out_size); @@ -202,6 +204,8 @@ LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_GlobalVariable_getGlobalVariableExpr LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_GlobalVariable_getMetadata(LLVMValueRef global_variable, uint32_t KindID); +LLVMSHARP_LINKAGE uint8_t llvmsharp_InlineFunction(LLVMValueRef call_base); + LLVMSHARP_LINKAGE const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size); LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_isCommutative(LLVMValueRef instruction); From c5f6473fab92d8f2ad6e09454712659458b52cf7 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:06:19 -0700 Subject: [PATCH 07/11] Add native IR value and instruction utility helpers Expose Mangler::getNameWithPrefix, Value::stripPointerCastsAndAliases, Value::stripInBoundsOffsets, Value::getPointerAlignment, Instruction::comesBefore/moveBefore/moveAfter, and GEPOperator::accumulateConstantOffset, none of which the LLVM-C API surfaces. getNameWithPrefix heap-allocates the mangled name; the caller frees it via llvmsharp_Free. moveBefore uses the iterator overload since the Instruction* overload is deprecated. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 79 ++++++++++++++++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 16 ++++++ 2 files changed, 95 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 84f42f5f..047617f3 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -26,12 +26,15 @@ #include #include #include +#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -486,6 +489,21 @@ LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function) return wrap(type); } +uint8_t llvmsharp_GEPOperator_accumulateConstantOffset(LLVMValueRef gep, LLVMModuleRef module, int64_t* out_offset) +{ + GEPOperator* unwrapped = unwrap(gep); + const DataLayout& dataLayout = unwrap(module)->getDataLayout(); + unsigned bitWidth = dataLayout.getIndexTypeSizeInBits(unwrapped->getType()); + APInt offset(bitWidth, 0); + if (!unwrapped->accumulateConstantOffset(dataLayout, offset)) + { + *out_offset = 0; + return 0; + } + *out_offset = offset.getSExtValue(); + return 1; +} + uint32_t llvmsharp_GlobalValue_getAddressSpace(LLVMValueRef global_value) { GlobalValue* unwrapped = unwrap(global_value); @@ -525,6 +543,12 @@ uint8_t llvmsharp_InlineFunction(LLVMValueRef call_base) return result.isSuccess() ? 1 : 0; } +uint8_t llvmsharp_Instruction_comesBefore(LLVMValueRef instruction, LLVMValueRef other) +{ + Instruction* unwrapped = unwrap(instruction); + return unwrapped->comesBefore(unwrap(other)) ? 1 : 0; +} + const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size) { Instruction* unwrapped = unwrap(instruction); @@ -557,6 +581,19 @@ uint8_t llvmsharp_Instruction_mayWriteToMemory(LLVMValueRef instruction) return unwrapped->mayWriteToMemory() ? 1 : 0; } +void llvmsharp_Instruction_moveAfter(LLVMValueRef instruction, LLVMValueRef position) +{ + Instruction* unwrapped = unwrap(instruction); + unwrapped->moveAfter(unwrap(position)); +} + +void llvmsharp_Instruction_moveBefore(LLVMValueRef instruction, LLVMValueRef position) +{ + Instruction* unwrapped = unwrap(instruction); + Instruction* positionInstruction = unwrap(position); + unwrapped->moveBefore(positionInstruction->getIterator()); +} + LLVMSharpLoopInfoRef llvmsharp_LoopInfo_create(LLVMSharpDominatorTreeRef dominator_tree) { DominatorTree* unwrapped = unwrap(dominator_tree); @@ -622,6 +659,29 @@ LLVMSharpLoopRef llvmsharp_Loop_getParentLoop(LLVMSharpLoopRef loop) return wrap(unwrapped->getParentLoop()); } +const char* llvmsharp_Mangler_getNameWithPrefix(LLVMValueRef global_value, int32_t* out_size) +{ + GlobalValue* unwrapped = unwrap(global_value); + std::string result; + raw_string_ostream stream(result); + Mangler mangler; + mangler.getNameWithPrefix(stream, unwrapped, false); + stream.flush(); + + int32_t size = (int32_t)result.size(); + char* buffer = (char*)malloc((size_t)size + 1); + if (buffer == nullptr) + { + *out_size = 0; + return nullptr; // Memory allocation failed + } + + memcpy(buffer, result.data(), size); + buffer[size] = '\0'; + *out_size = size; + return buffer; +} + uint32_t llvmsharp_MDNode_getNumOperands(LLVMMetadataRef metadata) { MDNode* unwrapped = unwrap(metadata); @@ -773,12 +833,31 @@ uint32_t llvmsharp_Value_getNumUses(LLVMValueRef value) return (uint32_t)unwrapped->getNumUses(); } +uint64_t llvmsharp_Value_getPointerAlignment(LLVMValueRef value, LLVMModuleRef module) +{ + Value* unwrapped = unwrap(value); + const DataLayout& dataLayout = unwrap(module)->getDataLayout(); + return unwrapped->getPointerAlignment(dataLayout).value(); +} + +LLVMValueRef llvmsharp_Value_stripInBoundsOffsets(LLVMValueRef value) +{ + Value* unwrapped = unwrap(value); + return wrap(unwrapped->stripInBoundsOffsets()); +} + LLVMValueRef llvmsharp_Value_stripPointerCasts(LLVMValueRef value) { Value* unwrapped = unwrap(value); return wrap(unwrapped->stripPointerCasts()); } +LLVMValueRef llvmsharp_Value_stripPointerCastsAndAliases(LLVMValueRef value) +{ + Value* unwrapped = unwrap(value); + return wrap(unwrapped->stripPointerCastsAndAliases()); +} + LLVMPassRef llvmsharp_createDeadCodeEliminationPass() { return wrap((Pass*)createDeadCodeEliminationPass()); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 494fa0bb..0d31fb24 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -196,6 +196,8 @@ LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getFunctionType(LLVMValueRef fu LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function); +LLVMSHARP_LINKAGE uint8_t llvmsharp_GEPOperator_accumulateConstantOffset(LLVMValueRef gep, LLVMModuleRef module, int64_t* out_offset); + LLVMSHARP_LINKAGE uint32_t llvmsharp_GlobalValue_getAddressSpace(LLVMValueRef global_value); LLVMSHARP_LINKAGE uint8_t llvmsharp_GlobalValue_isDSOLocal(LLVMValueRef global_value); @@ -206,6 +208,8 @@ LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_GlobalVariable_getMetadata(LLVMValue LLVMSHARP_LINKAGE uint8_t llvmsharp_InlineFunction(LLVMValueRef call_base); +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_comesBefore(LLVMValueRef instruction, LLVMValueRef other); + LLVMSHARP_LINKAGE const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size); LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_isCommutative(LLVMValueRef instruction); @@ -216,6 +220,10 @@ LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayReadFromMemory(LLVMValueRef i LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayWriteToMemory(LLVMValueRef instruction); +LLVMSHARP_LINKAGE void llvmsharp_Instruction_moveAfter(LLVMValueRef instruction, LLVMValueRef position); + +LLVMSHARP_LINKAGE void llvmsharp_Instruction_moveBefore(LLVMValueRef instruction, LLVMValueRef position); + LLVMSHARP_LINKAGE LLVMSharpLoopInfoRef llvmsharp_LoopInfo_create(LLVMSharpDominatorTreeRef dominator_tree); LLVMSHARP_LINKAGE void llvmsharp_LoopInfo_dispose(LLVMSharpLoopInfoRef loop_info); @@ -238,6 +246,8 @@ LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getLoopPreheader(LLVMSharpLoo LLVMSHARP_LINKAGE LLVMSharpLoopRef llvmsharp_Loop_getParentLoop(LLVMSharpLoopRef loop); +LLVMSHARP_LINKAGE const char* llvmsharp_Mangler_getNameWithPrefix(LLVMValueRef global_value, int32_t* out_size); + LLVMSHARP_LINKAGE uint32_t llvmsharp_MDNode_getNumOperands(LLVMMetadataRef metadata); LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_MDNode_getOperand(LLVMMetadataRef metadata, uint32_t index); @@ -280,8 +290,14 @@ LLVMSHARP_LINKAGE uint32_t llvmsharp_Type_getScalarSizeInBits(LLVMTypeRef type); LLVMSHARP_LINKAGE uint32_t llvmsharp_Value_getNumUses(LLVMValueRef value); +LLVMSHARP_LINKAGE uint64_t llvmsharp_Value_getPointerAlignment(LLVMValueRef value, LLVMModuleRef module); + +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Value_stripInBoundsOffsets(LLVMValueRef value); + LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Value_stripPointerCasts(LLVMValueRef value); +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Value_stripPointerCastsAndAliases(LLVMValueRef value); + LLVMSHARP_LINKAGE LLVMPassRef llvmsharp_createDeadCodeEliminationPass(); LLVMSHARP_LINKAGE LLVMPassRef llvmsharp_createSROAPass(uint8_t PreserveCFG); From 384bb3cf3f84de3ca699a99ba490415c739138fe Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:48:06 -0700 Subject: [PATCH 08/11] Add native IR predicate and speculation-safety helpers Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 61 ++++++++++++++++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 20 ++++++++++ 2 files changed, 81 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 047617f3..195b2e4d 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -153,6 +154,24 @@ LLVMValueRef llvmsharp_ConstantFoldInstruction(LLVMValueRef instruction, LLVMMod return wrap(ConstantFoldInstruction(unwrapped, dataLayout)); } +uint8_t llvmsharp_Constant_isAllOnesValue(LLVMValueRef value) +{ + Constant* unwrapped = unwrap(value); + return unwrapped->isAllOnesValue() ? 1 : 0; +} + +uint8_t llvmsharp_Constant_isNegativeZeroValue(LLVMValueRef value) +{ + Constant* unwrapped = unwrap(value); + return unwrapped->isNegativeZeroValue() ? 1 : 0; +} + +uint8_t llvmsharp_Constant_isOneValue(LLVMValueRef value) +{ + Constant* unwrapped = unwrap(value); + return unwrapped->isOneValue() ? 1 : 0; +} + uint32_t llvmsharp_DIBasicType_getEncoding(LLVMMetadataRef type) { DIBasicType* unwrapped = unwrap(type); @@ -482,6 +501,12 @@ LLVMTypeRef llvmsharp_Function_getFunctionType(LLVMValueRef function) return wrap(type); } +uint32_t llvmsharp_Function_getInstructionCount(LLVMValueRef function) +{ + Function* unwrapped = unwrap(function); + return unwrapped->getInstructionCount(); +} + LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function) { Function* unwrapped = unwrap(function); @@ -543,6 +568,12 @@ uint8_t llvmsharp_InlineFunction(LLVMValueRef call_base) return result.isSuccess() ? 1 : 0; } +uint8_t llvmsharp_isSafeToSpeculativelyExecute(LLVMValueRef instruction) +{ + Instruction* unwrapped = unwrap(instruction); + return isSafeToSpeculativelyExecute(unwrapped) ? 1 : 0; +} + uint8_t llvmsharp_Instruction_comesBefore(LLVMValueRef instruction, LLVMValueRef other) { Instruction* unwrapped = unwrap(instruction); @@ -563,6 +594,18 @@ uint8_t llvmsharp_Instruction_isCommutative(LLVMValueRef instruction) return unwrapped->isCommutative() ? 1 : 0; } +uint8_t llvmsharp_Instruction_isIdenticalTo(LLVMValueRef instruction, LLVMValueRef other) +{ + Instruction* unwrapped = unwrap(instruction); + return unwrapped->isIdenticalTo(unwrap(other)) ? 1 : 0; +} + +uint8_t llvmsharp_Instruction_isSameOperationAs(LLVMValueRef instruction, LLVMValueRef other) +{ + Instruction* unwrapped = unwrap(instruction); + return unwrapped->isSameOperationAs(unwrap(other)) ? 1 : 0; +} + uint8_t llvmsharp_Instruction_mayHaveSideEffects(LLVMValueRef instruction) { Instruction* unwrapped = unwrap(instruction); @@ -840,6 +883,24 @@ uint64_t llvmsharp_Value_getPointerAlignment(LLVMValueRef value, LLVMModuleRef m return unwrapped->getPointerAlignment(dataLayout).value(); } +uint8_t llvmsharp_Value_hasOneUse(LLVMValueRef value) +{ + Value* unwrapped = unwrap(value); + return unwrapped->hasOneUse() ? 1 : 0; +} + +uint8_t llvmsharp_Value_hasOneUser(LLVMValueRef value) +{ + Value* unwrapped = unwrap(value); + return unwrapped->hasOneUser() ? 1 : 0; +} + +uint8_t llvmsharp_Value_isUsedInBasicBlock(LLVMValueRef value, LLVMBasicBlockRef basic_block) +{ + Value* unwrapped = unwrap(value); + return unwrapped->isUsedInBasicBlock(unwrap(basic_block)) ? 1 : 0; +} + LLVMValueRef llvmsharp_Value_stripInBoundsOffsets(LLVMValueRef value) { Value* unwrapped = unwrap(value); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 0d31fb24..72f9d796 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -112,6 +112,12 @@ LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_ConstantFoldConstant(LLVMValueRef const LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_ConstantFoldInstruction(LLVMValueRef instruction, LLVMModuleRef module); +LLVMSHARP_LINKAGE uint8_t llvmsharp_Constant_isAllOnesValue(LLVMValueRef value); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Constant_isNegativeZeroValue(LLVMValueRef value); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Constant_isOneValue(LLVMValueRef value); + LLVMSHARP_LINKAGE uint32_t llvmsharp_DIBasicType_getEncoding(LLVMMetadataRef type); LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_DICompositeType_getBaseType(LLVMMetadataRef type); @@ -194,6 +200,8 @@ LLVMSHARP_LINKAGE uint8_t llvmsharp_DominatorTree_properlyDominatesBlock(LLVMSha LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getFunctionType(LLVMValueRef function); +LLVMSHARP_LINKAGE uint32_t llvmsharp_Function_getInstructionCount(LLVMValueRef function); + LLVMSHARP_LINKAGE LLVMTypeRef llvmsharp_Function_getReturnType(LLVMValueRef function); LLVMSHARP_LINKAGE uint8_t llvmsharp_GEPOperator_accumulateConstantOffset(LLVMValueRef gep, LLVMModuleRef module, int64_t* out_offset); @@ -208,12 +216,18 @@ LLVMSHARP_LINKAGE LLVMMetadataRef llvmsharp_GlobalVariable_getMetadata(LLVMValue LLVMSHARP_LINKAGE uint8_t llvmsharp_InlineFunction(LLVMValueRef call_base); +LLVMSHARP_LINKAGE uint8_t llvmsharp_isSafeToSpeculativelyExecute(LLVMValueRef instruction); + LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_comesBefore(LLVMValueRef instruction, LLVMValueRef other); LLVMSHARP_LINKAGE const char* llvmsharp_Instruction_getOpcodeName(LLVMValueRef instruction, int32_t* out_size); LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_isCommutative(LLVMValueRef instruction); +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_isIdenticalTo(LLVMValueRef instruction, LLVMValueRef other); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_isSameOperationAs(LLVMValueRef instruction, LLVMValueRef other); + LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayHaveSideEffects(LLVMValueRef instruction); LLVMSHARP_LINKAGE uint8_t llvmsharp_Instruction_mayReadFromMemory(LLVMValueRef instruction); @@ -292,6 +306,12 @@ LLVMSHARP_LINKAGE uint32_t llvmsharp_Value_getNumUses(LLVMValueRef value); LLVMSHARP_LINKAGE uint64_t llvmsharp_Value_getPointerAlignment(LLVMValueRef value, LLVMModuleRef module); +LLVMSHARP_LINKAGE uint8_t llvmsharp_Value_hasOneUse(LLVMValueRef value); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Value_hasOneUser(LLVMValueRef value); + +LLVMSHARP_LINKAGE uint8_t llvmsharp_Value_isUsedInBasicBlock(LLVMValueRef value, LLVMBasicBlockRef basic_block); + LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Value_stripInBoundsOffsets(LLVMValueRef value); LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Value_stripPointerCasts(LLVMValueRef value); From 24b292ae2e2ad5b7085fd6b5bb621f1dec448613 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:48:48 -0700 Subject: [PATCH 09/11] Add native basic-block insertion-point helpers Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 23 +++++++++++++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 195b2e4d..9359a6c0 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,28 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetTransformInfo, LLVMSharpTargetTransform // Implementation code +LLVMValueRef llvmsharp_BasicBlock_getFirstInsertionPt(LLVMBasicBlockRef basic_block) +{ + BasicBlock* unwrapped = unwrap(basic_block); + BasicBlock::iterator it = unwrapped->getFirstInsertionPt(); + if (it == unwrapped->end()) + { + return nullptr; + } + return wrap(&*it); +} + +LLVMValueRef llvmsharp_BasicBlock_getFirstNonPHI(LLVMBasicBlockRef basic_block) +{ + BasicBlock* unwrapped = unwrap(basic_block); + BasicBlock::iterator it = unwrapped->getFirstNonPHIIt(); + if (it == unwrapped->end()) + { + return nullptr; + } + return wrap(&*it); +} + uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call) { CallBase* unwrapped = unwrap(call); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 72f9d796..7ddd5551 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -86,6 +86,10 @@ LLVM_CLANG_C_EXTERN_C_BEGIN // Function declarations +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_BasicBlock_getFirstInsertionPt(LLVMBasicBlockRef basic_block); + +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_BasicBlock_getFirstNonPHI(LLVMBasicBlockRef basic_block); + LLVMSHARP_LINKAGE uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call); LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_CloneFunction(LLVMValueRef function); From c22ecb294aa68d86f7eb51fed6958ea69606a2f4 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 19:49:26 -0700 Subject: [PATCH 10/11] Add native loop induction-variable and exiting-block helpers Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 12 ++++++++++++ sources/libLLVMSharp/LLVMSharp.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 9359a6c0..725f533e 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -689,12 +689,24 @@ uint8_t llvmsharp_Loop_containsBlock(LLVMSharpLoopRef loop, LLVMBasicBlockRef bl return unwrapped->contains(unwrap(block)) ? 1 : 0; } +LLVMValueRef llvmsharp_Loop_getCanonicalInductionVariable(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getCanonicalInductionVariable()); +} + LLVMBasicBlockRef llvmsharp_Loop_getExitBlock(LLVMSharpLoopRef loop) { Loop* unwrapped = unwrap(loop); return wrap(unwrapped->getExitBlock()); } +LLVMBasicBlockRef llvmsharp_Loop_getExitingBlock(LLVMSharpLoopRef loop) +{ + Loop* unwrapped = unwrap(loop); + return wrap(unwrapped->getExitingBlock()); +} + LLVMBasicBlockRef llvmsharp_Loop_getHeader(LLVMSharpLoopRef loop) { Loop* unwrapped = unwrap(loop); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index 7ddd5551..f56f23fb 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -252,8 +252,12 @@ LLVMSHARP_LINKAGE LLVMSharpLoopRef llvmsharp_LoopInfo_getLoopFor(LLVMSharpLoopIn LLVMSHARP_LINKAGE uint8_t llvmsharp_Loop_containsBlock(LLVMSharpLoopRef loop, LLVMBasicBlockRef block); +LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_Loop_getCanonicalInductionVariable(LLVMSharpLoopRef loop); + LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getExitBlock(LLVMSharpLoopRef loop); +LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getExitingBlock(LLVMSharpLoopRef loop); + LLVMSHARP_LINKAGE LLVMBasicBlockRef llvmsharp_Loop_getHeader(LLVMSharpLoopRef loop); LLVMSHARP_LINKAGE uint32_t llvmsharp_Loop_getLoopDepth(LLVMSharpLoopRef loop); From efe6b87fe2bdb28ec99723d7ff79401890de0934 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 15 Jul 2026 21:26:41 -0700 Subject: [PATCH 11/11] Remove redundant native CmpInst predicate helpers The inverse/swapped predicate transforms and the signed/unsigned/true-when-equal/false-when-equal predicate classifications are pure functions of the predicate enum, so they are emulated managed-side from CmpInst.GetPredicate() and don't need a native round-trip. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sources/libLLVMSharp/LLVMSharp.cpp | 36 ------------------------------ sources/libLLVMSharp/LLVMSharp.h | 12 ---------- 2 files changed, 48 deletions(-) diff --git a/sources/libLLVMSharp/LLVMSharp.cpp b/sources/libLLVMSharp/LLVMSharp.cpp index 725f533e..f1120908 100644 --- a/sources/libLLVMSharp/LLVMSharp.cpp +++ b/sources/libLLVMSharp/LLVMSharp.cpp @@ -103,12 +103,6 @@ LLVMValueRef llvmsharp_CloneFunction(LLVMValueRef function) return wrap(CloneFunction(unwrapped, valueMap)); } -int32_t llvmsharp_CmpInst_getInversePredicate(LLVMValueRef instruction) -{ - CmpInst* unwrapped = unwrap(instruction); - return (int32_t)unwrapped->getInversePredicate(); -} - const char* llvmsharp_CmpInst_getPredicateName(LLVMValueRef instruction, int32_t* out_size) { CmpInst* unwrapped = unwrap(instruction); @@ -117,36 +111,6 @@ const char* llvmsharp_CmpInst_getPredicateName(LLVMValueRef instruction, int32_t return name.data(); } -int32_t llvmsharp_CmpInst_getSwappedPredicate(LLVMValueRef instruction) -{ - CmpInst* unwrapped = unwrap(instruction); - return (int32_t)unwrapped->getSwappedPredicate(); -} - -uint8_t llvmsharp_CmpInst_isFalseWhenEqual(LLVMValueRef instruction) -{ - CmpInst* unwrapped = unwrap(instruction); - return unwrapped->isFalseWhenEqual() ? 1 : 0; -} - -uint8_t llvmsharp_CmpInst_isSigned(LLVMValueRef instruction) -{ - CmpInst* unwrapped = unwrap(instruction); - return unwrapped->isSigned() ? 1 : 0; -} - -uint8_t llvmsharp_CmpInst_isTrueWhenEqual(LLVMValueRef instruction) -{ - CmpInst* unwrapped = unwrap(instruction); - return unwrapped->isTrueWhenEqual() ? 1 : 0; -} - -uint8_t llvmsharp_CmpInst_isUnsigned(LLVMValueRef instruction) -{ - CmpInst* unwrapped = unwrap(instruction); - return unwrapped->isUnsigned() ? 1 : 0; -} - const char* llvmsharp_ConstantDataArray_getData(LLVMValueRef array, int32_t* out_size) { ConstantDataArray* unwrapped = unwrap(array); diff --git a/sources/libLLVMSharp/LLVMSharp.h b/sources/libLLVMSharp/LLVMSharp.h index f56f23fb..53a77c84 100644 --- a/sources/libLLVMSharp/LLVMSharp.h +++ b/sources/libLLVMSharp/LLVMSharp.h @@ -94,20 +94,8 @@ LLVMSHARP_LINKAGE uint8_t llvmsharp_CallBase_isIndirectCall(LLVMValueRef call); LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_CloneFunction(LLVMValueRef function); -LLVMSHARP_LINKAGE int32_t llvmsharp_CmpInst_getInversePredicate(LLVMValueRef instruction); - LLVMSHARP_LINKAGE const char* llvmsharp_CmpInst_getPredicateName(LLVMValueRef instruction, int32_t* out_size); -LLVMSHARP_LINKAGE int32_t llvmsharp_CmpInst_getSwappedPredicate(LLVMValueRef instruction); - -LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isFalseWhenEqual(LLVMValueRef instruction); - -LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isSigned(LLVMValueRef instruction); - -LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isTrueWhenEqual(LLVMValueRef instruction); - -LLVMSHARP_LINKAGE uint8_t llvmsharp_CmpInst_isUnsigned(LLVMValueRef instruction); - LLVMSHARP_LINKAGE const char* llvmsharp_ConstantDataArray_getData(LLVMValueRef array, int32_t* out_size); LLVMSHARP_LINKAGE LLVMValueRef llvmsharp_ConstantFoldCompareInstOperands(int32_t predicate, LLVMValueRef lhs, LLVMValueRef rhs, LLVMModuleRef module);