Skip to content

Commit cdc1560

Browse files
committed
Additional GlobalValue support
1 parent 1e253c0 commit cdc1560

File tree

5 files changed

+167
-23
lines changed

5 files changed

+167
-23
lines changed

src/builder.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use either::Either;
2-
use llvm_sys::core::{LLVMBuildAdd, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc, LLVMBuildBr, LLVMBuildCall, LLVMBuildCast, LLVMBuildCondBr, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFence, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFree, LLVMBuildFSub, LLVMBuildGEP, LLVMBuildICmp, LLVMBuildInsertValue, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLoad, LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildStore, LLVMBuildSub, LLVMBuildUDiv, LLVMBuildUnreachable, LLVMBuildXor, LLVMDisposeBuilder, LLVMGetElementType, LLVMGetInsertBlock, LLVMGetReturnType, LLVMGetTypeKind, LLVMInsertIntoBuilder, LLVMPositionBuilderAtEnd, LLVMTypeOf, LLVMSetTailCall, LLVMBuildExtractElement, LLVMBuildInsertElement, LLVMBuildIntToPtr, LLVMBuildPtrToInt, LLVMInsertIntoBuilderWithName, LLVMClearInsertionPosition, LLVMCreateBuilder, LLVMPositionBuilder, LLVMPositionBuilderBefore, LLVMBuildAggregateRet, LLVMBuildStructGEP, LLVMBuildInBoundsGEP, LLVMBuildPtrDiff, LLVMBuildNSWAdd, LLVMBuildNUWAdd, LLVMBuildNSWSub, LLVMBuildNUWSub, LLVMBuildNSWMul, LLVMBuildNUWMul, LLVMBuildSDiv, LLVMBuildSRem, LLVMBuildURem, LLVMBuildFRem, LLVMBuildNSWNeg, LLVMBuildNUWNeg, LLVMBuildFPToUI, LLVMBuildFPToSI, LLVMBuildSIToFP, LLVMBuildUIToFP, LLVMBuildFPTrunc, LLVMBuildFPExt, LLVMBuildIntCast, LLVMBuildFPCast, LLVMBuildSExtOrBitCast, LLVMBuildZExtOrBitCast, LLVMBuildTruncOrBitCast, LLVMBuildSwitch, LLVMAddCase, LLVMBuildShl, LLVMBuildAShr, LLVMBuildLShr};
2+
use llvm_sys::core::{LLVMBuildAdd, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc, LLVMBuildBr, LLVMBuildCall, LLVMBuildCast, LLVMBuildCondBr, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFDiv, LLVMBuildFence, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFree, LLVMBuildFSub, LLVMBuildGEP, LLVMBuildICmp, LLVMBuildInsertValue, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLoad, LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi, LLVMBuildPointerCast, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildStore, LLVMBuildSub, LLVMBuildUDiv, LLVMBuildUnreachable, LLVMBuildXor, LLVMDisposeBuilder, LLVMGetElementType, LLVMGetInsertBlock, LLVMGetReturnType, LLVMGetTypeKind, LLVMInsertIntoBuilder, LLVMPositionBuilderAtEnd, LLVMTypeOf, LLVMSetTailCall, LLVMBuildExtractElement, LLVMBuildInsertElement, LLVMBuildIntToPtr, LLVMBuildPtrToInt, LLVMInsertIntoBuilderWithName, LLVMClearInsertionPosition, LLVMCreateBuilder, LLVMPositionBuilder, LLVMPositionBuilderBefore, LLVMBuildAggregateRet, LLVMBuildStructGEP, LLVMBuildInBoundsGEP, LLVMBuildPtrDiff, LLVMBuildNSWAdd, LLVMBuildNUWAdd, LLVMBuildNSWSub, LLVMBuildNUWSub, LLVMBuildNSWMul, LLVMBuildNUWMul, LLVMBuildSDiv, LLVMBuildSRem, LLVMBuildURem, LLVMBuildFRem, LLVMBuildNSWNeg, LLVMBuildNUWNeg, LLVMBuildFPToUI, LLVMBuildFPToSI, LLVMBuildSIToFP, LLVMBuildUIToFP, LLVMBuildFPTrunc, LLVMBuildFPExt, LLVMBuildIntCast, LLVMBuildFPCast, LLVMBuildSExtOrBitCast, LLVMBuildZExtOrBitCast, LLVMBuildTruncOrBitCast, LLVMBuildSwitch, LLVMAddCase, LLVMBuildShl, LLVMBuildAShr, LLVMBuildLShr, LLVMBuildGlobalString, LLVMBuildGlobalStringPtr};
33
use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef};
44
use llvm_sys::{LLVMOpcode, LLVMTypeKind, LLVMAtomicOrdering};
55

66
use {IntPredicate, FloatPredicate};
77
use basic_block::BasicBlock;
8-
use values::{AggregateValue, AsValueRef, BasicValue, BasicValueEnum, PhiValue, FunctionValue, FloatValue, IntValue, PointerValue, VectorValue, InstructionValue};
8+
use values::{AggregateValue, AsValueRef, BasicValue, BasicValueEnum, PhiValue, FunctionValue, FloatValue, IntValue, PointerValue, VectorValue, InstructionValue, GlobalValue};
99
use types::{AsTypeRef, BasicType, PointerType, IntType, FloatType};
1010

1111
use std::ffi::CString;
@@ -985,6 +985,26 @@ impl Builder {
985985

986986
InstructionValue::new(switch_value)
987987
}
988+
989+
pub fn build_global_string(&self, value: &str, name: &str) -> GlobalValue {
990+
let c_string_value = CString::new(value).expect("Conversion to CString failed unexpectedly");
991+
let c_string_name = CString::new(name).expect("Conversion to CString failed unexpectedly");
992+
let value = unsafe {
993+
LLVMBuildGlobalString(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr())
994+
};
995+
996+
GlobalValue::new(value)
997+
}
998+
999+
pub fn build_global_string_ptr(&self, value: &str, name: &str) -> GlobalValue {
1000+
let c_string_value = CString::new(value).expect("Conversion to CString failed unexpectedly");
1001+
let c_string_name = CString::new(name).expect("Conversion to CString failed unexpectedly");
1002+
let value = unsafe {
1003+
LLVMBuildGlobalStringPtr(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr())
1004+
};
1005+
1006+
GlobalValue::new(value)
1007+
}
9881008
}
9891009

9901010
impl Drop for Builder {

src/lib.rs

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub mod targets;
1717
pub mod types;
1818
pub mod values;
1919

20-
use llvm_sys::{LLVMIntPredicate, LLVMRealPredicate, LLVMVisibility};
20+
use llvm_sys::{LLVMIntPredicate, LLVMRealPredicate, LLVMVisibility, LLVMThreadLocalMode, LLVMDLLStorageClass};
2121

2222
// TODO: Probably move into error handling module
2323
pub fn enable_llvm_pretty_stack_trace() {
@@ -50,6 +50,7 @@ pub fn shutdown_llvm() {
5050
}
5151

5252
// REVIEW: Maybe this belongs in some sort of prelude?
53+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5354
pub enum IntPredicate {
5455
EQ,
5556
NE,
@@ -81,6 +82,7 @@ impl IntPredicate {
8182
}
8283

8384
// REVIEW: Maybe this belongs in some sort of prelude?
85+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8486
pub enum FloatPredicate {
8587
PredicateFalse,
8688
OEQ,
@@ -124,26 +126,82 @@ impl FloatPredicate {
124126
}
125127

126128
// REVIEW: Maybe this belongs in some sort of prelude?
129+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
127130
pub enum GlobalVisibility {
128131
Default,
129132
Hidden,
130133
Protected,
131134
}
132135

133136
impl GlobalVisibility {
137+
pub(crate) fn new(visibility: LLVMVisibility) -> Self {
138+
match visibility {
139+
LLVMVisibility::LLVMDefaultVisibility => GlobalVisibility::Default,
140+
LLVMVisibility::LLVMHiddenVisibility => GlobalVisibility::Hidden,
141+
LLVMVisibility::LLVMProtectedVisibility => GlobalVisibility::Protected,
142+
}
143+
}
144+
134145
pub(crate) fn as_llvm_visibility(&self) -> LLVMVisibility {
135146
match *self {
136147
GlobalVisibility::Default => LLVMVisibility::LLVMDefaultVisibility,
137148
GlobalVisibility::Hidden => LLVMVisibility::LLVMHiddenVisibility,
138149
GlobalVisibility::Protected => LLVMVisibility::LLVMProtectedVisibility,
139150
}
140151
}
152+
}
141153

142-
pub(crate) fn from_llvm_visibility(visibility: LLVMVisibility) -> Self {
143-
match visibility {
144-
LLVMVisibility::LLVMDefaultVisibility => GlobalVisibility::Default,
145-
LLVMVisibility::LLVMHiddenVisibility => GlobalVisibility::Hidden,
146-
LLVMVisibility::LLVMProtectedVisibility => GlobalVisibility::Protected,
154+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
155+
pub enum ThreadLocalMode {
156+
GeneralDynamicTLSModel,
157+
LocalDynamicTLSModel,
158+
InitialExecTLSModel,
159+
LocalExecTLSModel,
160+
}
161+
162+
impl ThreadLocalMode {
163+
pub(crate) fn new(thread_local_mode: LLVMThreadLocalMode) -> Option<Self> {
164+
match thread_local_mode {
165+
LLVMThreadLocalMode::LLVMGeneralDynamicTLSModel => Some(ThreadLocalMode::GeneralDynamicTLSModel),
166+
LLVMThreadLocalMode::LLVMLocalDynamicTLSModel => Some(ThreadLocalMode::LocalDynamicTLSModel),
167+
LLVMThreadLocalMode::LLVMInitialExecTLSModel => Some(ThreadLocalMode::InitialExecTLSModel),
168+
LLVMThreadLocalMode::LLVMLocalExecTLSModel => Some(ThreadLocalMode::LocalExecTLSModel),
169+
LLVMThreadLocalMode::LLVMNotThreadLocal => None
170+
}
171+
}
172+
173+
pub(crate) fn as_llvm_mode(&self) -> LLVMThreadLocalMode {
174+
match *self {
175+
ThreadLocalMode::GeneralDynamicTLSModel => LLVMThreadLocalMode::LLVMGeneralDynamicTLSModel,
176+
ThreadLocalMode::LocalDynamicTLSModel => LLVMThreadLocalMode::LLVMLocalDynamicTLSModel,
177+
ThreadLocalMode::InitialExecTLSModel => LLVMThreadLocalMode::LLVMInitialExecTLSModel,
178+
ThreadLocalMode::LocalExecTLSModel => LLVMThreadLocalMode::LLVMLocalExecTLSModel,
179+
// None => LLVMThreadLocalMode::LLVMNotThreadLocal,
180+
}
181+
}
182+
}
183+
184+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
185+
pub enum DLLStorageClass {
186+
Default,
187+
Import,
188+
Export,
189+
}
190+
191+
impl DLLStorageClass {
192+
pub(crate) fn new(dll_storage_class: LLVMDLLStorageClass) -> Self {
193+
match dll_storage_class {
194+
LLVMDLLStorageClass::LLVMDefaultStorageClass => DLLStorageClass::Default,
195+
LLVMDLLStorageClass::LLVMDLLImportStorageClass => DLLStorageClass::Import,
196+
LLVMDLLStorageClass::LLVMDLLExportStorageClass => DLLStorageClass::Export,
197+
}
198+
}
199+
200+
pub(crate) fn as_llvm_class(&self) -> LLVMDLLStorageClass {
201+
match *self {
202+
DLLStorageClass::Default => LLVMDLLStorageClass::LLVMDefaultStorageClass,
203+
DLLStorageClass::Import => LLVMDLLStorageClass::LLVMDLLImportStorageClass,
204+
DLLStorageClass::Export => LLVMDLLStorageClass::LLVMDLLExportStorageClass,
147205
}
148206
}
149207
}

src/module.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use llvm_sys::analysis::{LLVMVerifyModule, LLVMVerifierFailureAction};
22
use llvm_sys::bit_writer::{LLVMWriteBitcodeToFile, LLVMWriteBitcodeToMemoryBuffer, LLVMWriteBitcodeToFD};
3-
use llvm_sys::core::{LLVMAddFunction, LLVMAddGlobal, LLVMDisposeMessage, LLVMDumpModule, LLVMGetNamedFunction, LLVMGetTypeByName, LLVMSetDataLayout, LLVMSetInitializer, LLVMSetTarget, LLVMCloneModule, LLVMDisposeModule, LLVMGetTarget, LLVMGetDataLayout, LLVMModuleCreateWithName, LLVMGetModuleContext, LLVMGetFirstFunction, LLVMGetLastFunction, LLVMSetLinkage, LLVMAddGlobalInAddressSpace, LLVMPrintModuleToString, LLVMGetNamedMetadataNumOperands, LLVMAddNamedMetadataOperand, LLVMGetNamedMetadataOperands, LLVMGetFirstGlobal, LLVMGetLastGlobal, LLVMGetNamedGlobal};
3+
use llvm_sys::core::{LLVMAddFunction, LLVMAddGlobal, LLVMDisposeMessage, LLVMDumpModule, LLVMGetNamedFunction, LLVMGetTypeByName, LLVMSetDataLayout, LLVMSetTarget, LLVMCloneModule, LLVMDisposeModule, LLVMGetTarget, LLVMGetDataLayout, LLVMModuleCreateWithName, LLVMGetModuleContext, LLVMGetFirstFunction, LLVMGetLastFunction, LLVMSetLinkage, LLVMAddGlobalInAddressSpace, LLVMPrintModuleToString, LLVMGetNamedMetadataNumOperands, LLVMAddNamedMetadataOperand, LLVMGetNamedMetadataOperands, LLVMGetFirstGlobal, LLVMGetLastGlobal, LLVMGetNamedGlobal};
44
use llvm_sys::execution_engine::{LLVMCreateJITCompilerForModule, LLVMCreateMCJITCompilerForModule};
55
use llvm_sys::prelude::{LLVMValueRef, LLVMModuleRef};
66
use llvm_sys::LLVMLinkage;
@@ -20,7 +20,7 @@ use types::{AsTypeRef, BasicType, FunctionType, BasicTypeEnum};
2020
use values::{AsValueRef, BasicValue, FunctionValue, GlobalValue, MetadataValue};
2121

2222
// REVIEW: Maybe this should go into it's own module?
23-
#[derive(Debug, PartialEq, Eq)]
23+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
2424
pub enum Linkage {
2525
AppendingLinkage,
2626
AvailableExternallyLinkage,
@@ -241,7 +241,7 @@ impl Module {
241241
Ok(execution_engine)
242242
}
243243

244-
pub fn add_global(&self, type_: &BasicType, initial_value: Option<&BasicValue>, address_space: Option<u32>, name: &str) -> GlobalValue {
244+
pub fn add_global(&self, type_: &BasicType, address_space: Option<u32>, name: &str) -> GlobalValue {
245245
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
246246

247247
let value = unsafe {
@@ -251,12 +251,6 @@ impl Module {
251251
}
252252
};
253253

254-
if let Some(init_val) = initial_value {
255-
unsafe {
256-
LLVMSetInitializer(value, init_val.as_value_ref())
257-
}
258-
}
259-
260254
GlobalValue::new(value)
261255
}
262256

src/targets.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use context::Context;
66
use data_layout::DataLayout;
77
use passes::PassManager;
88
use types::{AnyType, AsTypeRef, StructType, PointerType};
9-
use values::AnyValue;
9+
use values::{AsValueRef, GlobalValue};
1010

1111
use std::default::Default;
1212
use std::ffi::{CStr, CString};
@@ -870,7 +870,7 @@ impl TargetData {
870870
}
871871
}
872872

873-
pub fn get_preferred_alignment_of_global(&self, value: &AnyValue) -> u32 {
873+
pub fn get_preferred_alignment_of_global(&self, value: &GlobalValue) -> u32 {
874874
unsafe {
875875
LLVMPreferredAlignmentOfGlobal(self.target_data, value.as_value_ref())
876876
}

src/values/global_value.rs

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use llvm_sys::core::{LLVMGetVisibility, LLVMSetVisibility, LLVMGetSection, LLVMSetSection, LLVMIsExternallyInitialized, LLVMSetExternallyInitialized, LLVMDeleteGlobal, LLVMIsGlobalConstant, LLVMSetGlobalConstant, LLVMGetPreviousGlobal, LLVMGetNextGlobal, LLVMHasUnnamedAddr, LLVMSetUnnamedAddr};
1+
use llvm_sys::LLVMThreadLocalMode;
2+
use llvm_sys::core::{LLVMGetVisibility, LLVMSetVisibility, LLVMGetSection, LLVMSetSection, LLVMIsExternallyInitialized, LLVMSetExternallyInitialized, LLVMDeleteGlobal, LLVMIsGlobalConstant, LLVMSetGlobalConstant, LLVMGetPreviousGlobal, LLVMGetNextGlobal, LLVMHasUnnamedAddr, LLVMSetUnnamedAddr, LLVMIsThreadLocal, LLVMSetThreadLocal, LLVMGetThreadLocalMode, LLVMSetThreadLocalMode, LLVMGetInitializer, LLVMSetInitializer, LLVMIsDeclaration, LLVMGetDLLStorageClass, LLVMSetDLLStorageClass};
23
use llvm_sys::prelude::LLVMValueRef;
34

45
use std::ffi::{CString, CStr};
56

6-
use GlobalVisibility;
7+
use {GlobalVisibility, ThreadLocalMode, DLLStorageClass};
78
use values::traits::AsValueRef;
8-
use values::{BasicValueEnum, Value};
9+
use values::{BasicValueEnum, BasicValue, Value};
910

1011
// REVIEW: GlobalValues may always be PointerValues, in which case we can
1112
// simplify from BasicValueEnum down to PointerValue
@@ -47,6 +48,77 @@ impl GlobalValue {
4748
Some(GlobalValue::new(value))
4849
}
4950

51+
pub fn get_dll_storage_class(&self) -> DLLStorageClass {
52+
let dll_storage_class = unsafe {
53+
LLVMGetDLLStorageClass(self.as_value_ref())
54+
};
55+
56+
DLLStorageClass::new(dll_storage_class)
57+
}
58+
59+
pub fn set_dll_storage_class(&self , dll_storage_class: &DLLStorageClass) {
60+
unsafe {
61+
LLVMSetDLLStorageClass(self.as_value_ref(), dll_storage_class.as_llvm_class())
62+
}
63+
}
64+
65+
pub fn get_initializer(&self) -> Option<BasicValueEnum> {
66+
let value = unsafe {
67+
LLVMGetInitializer(self.as_value_ref())
68+
};
69+
70+
if value.is_null() {
71+
return None;
72+
}
73+
74+
Some(BasicValueEnum::new(value))
75+
}
76+
77+
pub fn set_initializer(&self, value: &BasicValue) {
78+
unsafe {
79+
LLVMSetInitializer(self.as_value_ref(), value.as_value_ref())
80+
}
81+
}
82+
83+
pub fn is_thread_local(&self) -> bool {
84+
unsafe {
85+
LLVMIsThreadLocal(self.as_value_ref()) == 1
86+
}
87+
}
88+
89+
pub fn set_thread_local(&self, is_thread_local: bool) {
90+
unsafe {
91+
LLVMSetThreadLocal(self.as_value_ref(), is_thread_local as i32)
92+
}
93+
}
94+
95+
pub fn get_thread_local_mode(&self) -> Option<ThreadLocalMode> {
96+
let thread_local_mode = unsafe {
97+
LLVMGetThreadLocalMode(self.as_value_ref())
98+
};
99+
100+
ThreadLocalMode::new(thread_local_mode)
101+
}
102+
103+
// REVIEW: Does this have any bad behavior if it isn't thread local or just a noop?
104+
// or should it call self.set_thread_local(true)?
105+
pub fn set_thread_local_mode(&self, thread_local_mode: Option<&ThreadLocalMode>) {
106+
let thread_local_mode = match thread_local_mode {
107+
Some(mode) => mode.as_llvm_mode(),
108+
None => LLVMThreadLocalMode::LLVMNotThreadLocal,
109+
};
110+
111+
unsafe {
112+
LLVMSetThreadLocalMode(self.as_value_ref(), thread_local_mode)
113+
}
114+
}
115+
116+
pub fn is_declaration(&self) -> bool {
117+
unsafe {
118+
LLVMIsDeclaration(self.as_value_ref()) == 1
119+
}
120+
}
121+
50122
pub fn has_unnamed_addr(&self) -> bool {
51123
unsafe {
52124
LLVMHasUnnamedAddr(self.as_value_ref()) == 1
@@ -94,7 +166,7 @@ impl GlobalValue {
94166
LLVMGetVisibility(self.as_value_ref())
95167
};
96168

97-
GlobalVisibility::from_llvm_visibility(visibility)
169+
GlobalVisibility::new(visibility)
98170
}
99171

100172
pub fn get_section(&self) -> &CStr {

0 commit comments

Comments
 (0)