Skip to content

Commit 899fc8d

Browse files
committed
Initial support for more BasicBlock, FunctionValue, & InstructionValue methods
1 parent 227391e commit 899fc8d

File tree

3 files changed

+136
-6
lines changed

3 files changed

+136
-6
lines changed

src/basic_block.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMInsertBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock};
1+
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMInsertBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock, LLVMRemoveBasicBlockFromParent, LLVMGetFirstInstruction, LLVMGetLastInstruction};
22
use llvm_sys::prelude::{LLVMValueRef, LLVMBasicBlockRef};
33

44
use values::{FunctionValue, InstructionValue};
@@ -86,12 +86,43 @@ impl BasicBlock {
8686
BasicBlock::new(bb).expect("Prepending basic block should never fail")
8787
}
8888

89-
// REVIEW: Could potentially be unsafe if there are existing references. Might need a global ref counter
90-
pub fn delete(self) {
89+
pub fn get_first_instruction(&self) -> Option<InstructionValue> {
90+
let value = unsafe {
91+
LLVMGetFirstInstruction(self.basic_block)
92+
};
93+
94+
if value.is_null() {
95+
return None;
96+
}
97+
98+
Some(InstructionValue::new(value))
99+
}
100+
101+
pub fn get_last_instruction(&self) -> Option<InstructionValue> {
102+
let value = unsafe {
103+
LLVMGetLastInstruction(self.basic_block)
104+
};
105+
106+
if value.is_null() {
107+
return None;
108+
}
109+
110+
Some(InstructionValue::new(value))
111+
}
112+
113+
// REVIEW: Potentially unsafe if parent was deleted
114+
pub fn remove_from_function(&self) {
91115
unsafe {
92-
LLVMDeleteBasicBlock(self.basic_block)
116+
LLVMRemoveBasicBlockFromParent(self.basic_block)
93117
}
94118
}
119+
120+
// REVIEW: Could potentially be unsafe if there are existing references. Might need a global ref counter
121+
pub unsafe fn delete(self) {
122+
// unsafe {
123+
LLVMDeleteBasicBlock(self.basic_block)
124+
// }
125+
}
95126
}
96127

97128
impl fmt::Debug for BasicBlock {

src/values/fn_value.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction, LLVMViewFunctionCFG, LLVMViewFunctionCFGOnly};
2-
use llvm_sys::core::{LLVMIsAFunction, LLVMIsConstant, LLVMGetLinkage, LLVMTypeOf, LLVMGetPreviousFunction, LLVMGetNextFunction, LLVMGetParam, LLVMCountParams, LLVMGetLastParam, LLVMCountBasicBlocks, LLVMGetFirstParam, LLVMGetNextParam, LLVMGetBasicBlocks, LLVMGetReturnType, LLVMAppendBasicBlock, LLVMDeleteFunction, LLVMGetElementType, LLVMGetLastBasicBlock, LLVMGetFirstBasicBlock, LLVMGetEntryBasicBlock};
2+
use llvm_sys::core::{LLVMIsAFunction, LLVMIsConstant, LLVMGetLinkage, LLVMTypeOf, LLVMGetPreviousFunction, LLVMGetNextFunction, LLVMGetParam, LLVMCountParams, LLVMGetLastParam, LLVMCountBasicBlocks, LLVMGetFirstParam, LLVMGetNextParam, LLVMGetBasicBlocks, LLVMGetReturnType, LLVMAppendBasicBlock, LLVMDeleteFunction, LLVMGetElementType, LLVMGetLastBasicBlock, LLVMGetFirstBasicBlock, LLVMGetEntryBasicBlock, LLVMGetPersonalityFn, LLVMSetPersonalityFn, LLVMGetIntrinsicID, LLVMGetFunctionCallConv, LLVMSetFunctionCallConv, LLVMGetGC, LLVMSetGC};
33
use llvm_sys::prelude::{LLVMValueRef, LLVMBasicBlockRef};
44

55
use std::ffi::{CStr, CString};
@@ -248,6 +248,60 @@ impl FunctionValue {
248248
pub fn set_metadata(&self, metadata: &MetadataValue, kind_id: u32) {
249249
self.fn_value.set_metadata(metadata, kind_id)
250250
}
251+
252+
// TODOC: How this works as an exception handler
253+
// TODO: LLVM 3.9+
254+
// pub fn has_personality_function(&self) -> bool {
255+
// unsafe {
256+
// LLVMHasPersonalityFunction(self.as_value_ref())
257+
// }
258+
// }
259+
260+
pub fn get_personality_function(&self) -> Option<FunctionValue> {
261+
let value = unsafe {
262+
LLVMGetPersonalityFn(self.as_value_ref())
263+
};
264+
265+
FunctionValue::new(value)
266+
}
267+
268+
pub fn set_personality_function(&self, personality_fn: &FunctionValue) {
269+
unsafe {
270+
LLVMSetPersonalityFn(self.as_value_ref(), personality_fn.as_value_ref())
271+
}
272+
}
273+
274+
pub fn get_intrinsic_id(&self) -> u32 {
275+
unsafe {
276+
LLVMGetIntrinsicID(self.as_value_ref())
277+
}
278+
}
279+
280+
pub fn get_call_conventions(&self) -> u32 {
281+
unsafe {
282+
LLVMGetFunctionCallConv(self.as_value_ref())
283+
}
284+
}
285+
286+
pub fn set_call_conventions(&self, call_conventions: u32) {
287+
unsafe {
288+
LLVMSetFunctionCallConv(self.as_value_ref(), call_conventions)
289+
}
290+
}
291+
292+
pub fn get_gc(&self) -> &CStr {
293+
unsafe {
294+
CStr::from_ptr(LLVMGetGC(self.as_value_ref()))
295+
}
296+
}
297+
298+
pub fn set_gc(&self, gc: &str) {
299+
let c_string = CString::new(gc).expect("Conversion to CString failed unexpectedly");
300+
301+
unsafe {
302+
LLVMSetGC(self.as_value_ref(), c_string.as_ptr())
303+
}
304+
}
251305
}
252306

253307
impl AsValueRef for FunctionValue {

src/values/instruction_value.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use llvm_sys::core::{LLVMGetInstructionOpcode, LLVMIsTailCall};
1+
use llvm_sys::core::{LLVMGetInstructionOpcode, LLVMIsTailCall, LLVMGetPreviousInstruction, LLVMGetNextInstruction, LLVMGetInstructionParent, LLVMInstructionEraseFromParent};
22
use llvm_sys::LLVMOpcode;
33
use llvm_sys::prelude::LLVMValueRef;
44

5+
use basic_block::BasicBlock;
56
use values::traits::AsValueRef;
67
use values::Value;
78

@@ -176,6 +177,50 @@ impl InstructionValue {
176177
InstructionOpcode::new(opcode)
177178
}
178179

180+
pub fn get_previous_instruction(&self) -> Option<Self> {
181+
let value = unsafe {
182+
LLVMGetPreviousInstruction(self.as_value_ref())
183+
};
184+
185+
if value.is_null() {
186+
return None;
187+
}
188+
189+
Some(InstructionValue::new(value))
190+
}
191+
192+
pub fn get_next_instruction(&self) -> Option<Self> {
193+
let value = unsafe {
194+
LLVMGetNextInstruction(self.as_value_ref())
195+
};
196+
197+
if value.is_null() {
198+
return None;
199+
}
200+
201+
Some(InstructionValue::new(value))
202+
}
203+
204+
// REVIEW: Potentially unsafe if parent BB or grandparent fn were removed?
205+
// REVIEW: Is this actually an erase and should be (self)?
206+
pub fn remove_from_basic_block(&self) {
207+
unsafe {
208+
LLVMInstructionEraseFromParent(self.as_value_ref())
209+
}
210+
}
211+
212+
// REVIEW: Potentially unsafe is parent BB or grandparent fn was deleted
213+
// REVIEW: Should this *not* be an option? Parent should always exist,
214+
// but I doubt LLVM returns null if the parent BB (or grandparent FN)
215+
// was deleted... Invalid memory is more likely
216+
pub fn get_parent(&self) -> Option<BasicBlock> {
217+
let value = unsafe {
218+
LLVMGetInstructionParent(self.as_value_ref())
219+
};
220+
221+
BasicBlock::new(value)
222+
}
223+
179224
// REVIEW: See if necessary to check opcode == Call first.
180225
// Does it always return false otherwise?
181226
pub fn is_tail_call(&self) -> bool {

0 commit comments

Comments
 (0)