Skip to content

Commit c3ed99c

Browse files
committed
Added support for covnerting FunctionValue to GlobalValue
Which ultimately allows for conversion to PointerValue
1 parent 6796676 commit c3ed99c

File tree

4 files changed

+70
-34
lines changed

4 files changed

+70
-34
lines changed

src/module.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,8 +1329,7 @@ impl Module {
13291329
// SubTypes: Might need to return Option<BVE, MV<Enum>, or MV<String>>
13301330
#[llvm_versions(7.0 => latest)]
13311331
pub fn get_flag(&self, key: &str) -> Option<MetadataValue> {
1332-
use llvm_sys::core::{LLVMGetTypeKind, LLVMTypeOf, LLVMMetadataAsValue};
1333-
use llvm_sys::LLVMTypeKind;
1332+
use llvm_sys::core::{LLVMTypeOf, LLVMMetadataAsValue};
13341333

13351334
let flag = unsafe {
13361335
LLVMGetModuleFlag(self.module.get(), key.as_ptr() as *const i8, key.len())
@@ -1347,8 +1346,6 @@ impl Module {
13471346
LLVMMetadataAsValue(*ctx.context, flag)
13481347
};
13491348

1350-
let value = unsafe { LLVMGetTypeKind(LLVMTypeOf(flag_value)) };
1351-
13521349
Some(MetadataValue::new(flag_value))
13531350
}
13541351

src/values/fn_value.rs

Lines changed: 7 additions & 27 deletions
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, LLVMGetIntrinsicID, LLVMGetFunctionCallConv, LLVMSetFunctionCallConv, LLVMGetGC, LLVMSetGC, LLVMSetLinkage, LLVMSetParamAlignment, LLVMGetParams, LLVMIsDeclaration};
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, LLVMGetIntrinsicID, LLVMGetFunctionCallConv, LLVMSetFunctionCallConv, LLVMGetGC, LLVMSetGC, LLVMSetLinkage, LLVMSetParamAlignment, LLVMGetParams};
33
#[llvm_versions(3.7 => latest)]
44
use llvm_sys::core::{LLVMGetPersonalityFn, LLVMSetPersonalityFn};
55
#[llvm_versions(3.9 => latest)]
@@ -17,7 +17,7 @@ use module::Linkage;
1717
use support::LLVMString;
1818
use types::{BasicTypeEnum, FunctionType};
1919
use values::traits::AsValueRef;
20-
use values::{BasicValueEnum, Value, MetadataValue};
20+
use values::{BasicValueEnum, GlobalValue, Value, MetadataValue};
2121

2222
#[derive(PartialEq, Eq, Clone, Copy)]
2323
pub struct FunctionValue {
@@ -540,31 +540,11 @@ impl FunctionValue {
540540
}
541541
}
542542

543-
/// Determines whether or not a `FunctionValue` is a declaration based on
544-
/// whether or not it contains a body definition whatsoever
545-
///
546-
/// # Example
547-
///
548-
/// ```no_run
549-
/// use inkwell::context::Context;
550-
///
551-
/// let context = Context::create();
552-
/// let builder = context.create_builder();
553-
/// let module = context.create_module("my_mod");
554-
/// let void_type = context.void_type();
555-
/// let fn_type = void_type.fn_type(&[], false);
556-
/// let fn_value = module.add_function("my_func", fn_type, None);
557-
///
558-
/// assert!(fn_value.is_declaration());
559-
///
560-
/// fn_value.append_basic_block("entry");
561-
///
562-
/// assert!(!fn_value.is_declaration());
563-
/// ```
564-
pub fn is_declaration(&self) -> bool {
565-
unsafe {
566-
LLVMIsDeclaration(self.as_value_ref()) != 0
567-
}
543+
/// Gets the `GlobalValue` version of this `FunctionValue`. This allows
544+
/// you to further inspect its global properties or even convert it to
545+
/// a `PointerValue`.
546+
pub fn as_global_value(&self) -> GlobalValue {
547+
GlobalValue::new(self.as_value_ref())
568548
}
569549
}
570550

src/values/global_value.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use llvm_sys::prelude::LLVMValueRef;
77
use std::ffi::{CString, CStr};
88

99
use {GlobalVisibility, ThreadLocalMode, DLLStorageClass};
10+
use support::LLVMString;
1011
#[llvm_versions(7.0 => latest)]
1112
use comdat::Comdat;
1213
use values::traits::AsValueRef;
@@ -120,7 +121,26 @@ impl GlobalValue {
120121
}
121122

122123
// SubType: This should be moved into the type. GlobalValue<Initialized/Uninitialized>
123-
// TODO: FunctionValues as well?
124+
/// Determines whether or not a `GlobalValue` is a declaration or a definition.
125+
///
126+
/// # Example
127+
///
128+
/// ```no_run
129+
/// use inkwell::context::Context;
130+
///
131+
/// let context = Context::create();
132+
/// let builder = context.create_builder();
133+
/// let module = context.create_module("my_mod");
134+
/// let void_type = context.void_type();
135+
/// let fn_type = void_type.fn_type(&[], false);
136+
/// let fn_value = module.add_function("my_func", fn_type, None);
137+
///
138+
/// assert!(fn_value.as_global_value().is_declaration());
139+
///
140+
/// fn_value.append_basic_block("entry");
141+
///
142+
/// assert!(!fn_value.as_global_value().is_declaration());
143+
/// ```
124144
pub fn is_declaration(&self) -> bool {
125145
unsafe {
126146
LLVMIsDeclaration(self.as_value_ref()) == 1
@@ -256,6 +276,10 @@ impl GlobalValue {
256276
LLVMSetUnnamedAddress(self.as_value_ref(), address.as_llvm_enum())
257277
}
258278
}
279+
280+
pub fn print_to_string(&self) -> LLVMString {
281+
self.global_value.print_to_string()
282+
}
259283
}
260284

261285
impl AsValueRef for GlobalValue {

tests/all/test_values.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,13 +974,13 @@ fn test_phi_values() {
974974
let fn_type = void_type.fn_type(&[bool_type.into()], false);
975975
let fn_value = module.add_function("my_func", fn_type, None);
976976

977-
assert!(fn_value.is_declaration());
977+
assert!(fn_value.as_global_value().is_declaration());
978978

979979
let entry_block = fn_value.append_basic_block("entry");
980980
let then_block = fn_value.append_basic_block("then");
981981
let else_block = fn_value.append_basic_block("else");
982982

983-
assert!(!fn_value.is_declaration());
983+
assert!(!fn_value.as_global_value().is_declaration());
984984

985985
builder.position_at_end(&entry_block);
986986

@@ -1186,3 +1186,38 @@ fn test_consts() {
11861186
assert!(i32_param.get_zero_extended_constant().is_none());
11871187
assert!(f32_param.get_constant().is_none());
11881188
}
1189+
1190+
#[test]
1191+
fn test_function_value_to_global_to_pointer() {
1192+
let context = Context::create();
1193+
let builder = context.create_builder();
1194+
let module = context.create_module("my_mod");
1195+
let void_type = context.void_type();
1196+
let fn_type = void_type.fn_type(&[], false);
1197+
let fn_value = module.add_function("my_func", fn_type, None);
1198+
1199+
let fn_global_value = fn_value.as_global_value();
1200+
1201+
assert!(fn_global_value.is_declaration());
1202+
1203+
let bb = fn_value.append_basic_block("entry");
1204+
1205+
builder.position_at_end(&bb);
1206+
builder.build_return(None);
1207+
1208+
assert!(!fn_global_value.is_declaration());
1209+
assert_eq!(fn_global_value.get_dll_storage_class(), DLLStorageClass::Default);
1210+
1211+
fn_global_value.set_dll_storage_class(DLLStorageClass::Export);
1212+
1213+
assert_eq!(fn_global_value.get_dll_storage_class(), DLLStorageClass::Export);
1214+
assert!(fn_global_value.get_thread_local_mode().is_none());
1215+
assert_eq!(fn_global_value.get_visibility(), GlobalVisibility::Default);
1216+
1217+
let fn_ptr_value = fn_global_value.as_pointer_value();
1218+
let fn_ptr_type = fn_ptr_value.get_type();
1219+
1220+
assert!(!fn_ptr_value.is_null());
1221+
assert_eq!(*fn_ptr_value.get_name(), *CString::new("my_func").unwrap());
1222+
assert!(module.verify().is_ok());
1223+
}

0 commit comments

Comments
 (0)