Skip to content

Commit 94beaa9

Browse files
committed
Added new functionality for globals
1 parent 409ca02 commit 94beaa9

File tree

3 files changed

+179
-12
lines changed

3 files changed

+179
-12
lines changed

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ pub use block::BasicBlock;
2929
pub use compile::Compile;
3030
pub use context::{Context, GetContext};
3131
pub use engine::{JitEngine, JitOptions, Interpreter, ExecutionEngine, GenericValue, GenericValueCast};
32-
pub use module::{Module, Functions};
32+
pub use module::{AddressSpace, Module, Functions};
3333
pub use object::{ObjectFile, Symbol, Symbols};
3434
pub use target::{TargetData, Target};
3535
pub use ty::{FunctionType, StructType, Type};
36-
pub use value::{Arg, Attribute, Value, Function, Predicate};
36+
pub use value::{Arg, Attribute, Value, Function, GlobalValue, GlobalVariable, Linkage, Predicate};
3737
pub use util::CastFrom;

src/module.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::path::Path;
1616
use std::process::Command;
1717
use buffer::MemoryBuffer;
1818
use context::{Context, GetContext};
19-
use value::{Function, Value};
19+
use value::{Alias, Function, GlobalValue, GlobalVariable, Value};
2020
use ty::Type;
2121
use util;
2222

@@ -43,21 +43,31 @@ impl Module {
4343
unsafe { CSemiBox::new(core::LLVMModuleCreateWithNameInContext(c_name.as_ptr(), context.into())) }
4444
}
4545
/// Add a global to the module with the given type and name.
46-
pub fn add_global<'a>(&'a self, name: &str, ty: &'a Type) -> &'a Value {
46+
pub fn add_global<'a>(&'a self, name: &str, ty: &'a Type) -> &'a GlobalVariable {
4747
util::with_cstr(name, |ptr| unsafe {
4848
core::LLVMAddGlobal(self.into(), ty.into(), ptr).into()
4949
})
5050
}
51-
/// Add a constant global to the module with the given type, name and value.
52-
pub fn add_global_constant<'a>(&'a self, name: &str, val: &'a Value) -> &'a Value {
51+
/// Add a global variable to the module with the given type, name and initial value.
52+
pub fn add_global_in_address_space<'a>(&'a self, name: &str, ty: &'a Type, address: AddressSpace) -> &'a GlobalVariable {
5353
util::with_cstr(name, |ptr| unsafe {
54-
let global = core::LLVMAddGlobal(self.into(), val.get_type().into(), ptr);
55-
core::LLVMSetInitializer (global.into(), val.into());
56-
global.into()
54+
core::LLVMAddGlobalInAddressSpace(self.into(), ty.into(), ptr, address as u32).into()
55+
})
56+
}
57+
/// Add a global variable to the module with the given type, name and initial value.
58+
pub fn add_global_variable<'a>(&'a self, name: &str, val: &'a Value) -> &'a GlobalVariable {
59+
let global = self.add_global(name, val.get_type());
60+
global.set_initializer(val);
61+
global
62+
}
63+
/// Add a global to the module with the given type and name.
64+
pub fn add_global_alias<'a>(&'a self, name: &str, val: &'a GlobalValue) -> &'a Alias {
65+
util::with_cstr(name, |ptr| unsafe {
66+
core::LLVMAddAlias(self.into(), val.get_type().into(), val.into(), ptr).into()
5767
})
5868
}
5969
/// Get the global with the name given, or `None` if no global with that name exists.
60-
pub fn get_global<'a>(&'a self, name: &str) -> Option<&'a Value> {
70+
pub fn get_global<'a>(&'a self, name: &str) -> Option<&'a GlobalValue> {
6171
util::with_cstr(name, |ptr| unsafe {
6272
let ptr = core::LLVMGetNamedGlobal(self.into(), ptr);
6373
util::ptr_to_null(ptr)
@@ -238,3 +248,13 @@ impl<'a> Iterator for Functions<'a> {
238248
}
239249
}
240250
}
251+
252+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
253+
#[repr(C)]
254+
pub enum AddressSpace {
255+
Generic = 0,
256+
Global = 1,
257+
Shared = 3,
258+
Const = 4,
259+
Local = 5,
260+
}

src/value.rs

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use libc::{c_char, c_uint, c_int};
22
use ffi::prelude::LLVMValueRef;
33
use ffi::{core, LLVMAttribute};
4+
use ffi::LLVMLinkage;
45
use std::ffi::CString;
56
use std::{fmt, mem};
67
use std::ops::{Deref, Index};
@@ -109,12 +110,119 @@ impl Arg {
109110
unsafe { core::LLVMRemoveAttribute(self.into(), attr.into()) }
110111
}
111112
}
113+
114+
/// A global value (eg: Function, Alias, Global variable)
115+
pub struct GlobalValue;
116+
native_ref!(&GlobalValue = LLVMValueRef);
117+
impl Deref for GlobalValue {
118+
type Target = Value;
119+
fn deref(&self) -> &Value {
120+
unsafe { mem::transmute(self) }
121+
}
122+
}
123+
impl CastFrom for GlobalValue {
124+
type From = Value;
125+
fn cast<'a>(val: &'a Value) -> Option<&'a GlobalValue> {
126+
unsafe {
127+
let global = mem::transmute(core::LLVMIsAGlobalValue(val.into()));
128+
util::ptr_to_null(global)
129+
}
130+
}
131+
}
132+
impl GlobalValue {
133+
/// Set the linkage type for this global
134+
pub fn set_linkage(&self, linkage: Linkage) {
135+
unsafe {
136+
core::LLVMSetLinkage(self.into(), linkage.into());
137+
}
138+
}
139+
/// Returns the linkage type for this global
140+
pub fn get_linkage(&self) -> Linkage {
141+
unsafe {
142+
core::LLVMGetLinkage(self.into()).into()
143+
}
144+
}
145+
/// Returns true if this global is a declaration (as opposed to a definition).
146+
pub fn is_declaration(&self) -> bool {
147+
unsafe {
148+
// FIXME: There should be a constant somewhere, instead of '1'
149+
core::LLVMIsDeclaration(self.into()) == 1
150+
}
151+
}
152+
}
153+
154+
/// A global variable
155+
pub struct GlobalVariable;
156+
native_ref!(&GlobalVariable = LLVMValueRef);
157+
impl Deref for GlobalVariable {
158+
type Target = GlobalValue;
159+
fn deref(&self) -> &GlobalValue {
160+
unsafe { mem::transmute(self) }
161+
}
162+
}
163+
impl CastFrom for GlobalVariable {
164+
type From = Value;
165+
fn cast<'a>(val: &'a Value) -> Option<&'a GlobalVariable> {
166+
unsafe {
167+
let global = mem::transmute(core::LLVMIsAGlobalVariable(val.into()));
168+
util::ptr_to_null(global)
169+
}
170+
}
171+
}
172+
impl GlobalVariable {
173+
/// Set the initial value of the global
174+
pub fn set_initializer(&self, val: &Value) {
175+
unsafe {
176+
core::LLVMSetInitializer(self.into(), val.into())
177+
}
178+
}
179+
/// Set the initial value of the global
180+
pub fn get_initializer(&self) -> Option<&Value> {
181+
unsafe {
182+
util::ptr_to_null(core::LLVMGetInitializer(self.into()))
183+
}
184+
}
185+
/// Set whether this global is a constant.
186+
pub fn set_constant(&self, is_constant: bool) {
187+
let llvm_bool = if is_constant { 1 } else { 0 };
188+
unsafe {
189+
core::LLVMSetGlobalConstant(self.into(), llvm_bool);
190+
}
191+
}
192+
/// Returns true if this global is a constant.
193+
pub fn get_constant(&self) -> bool {
194+
unsafe {
195+
// FIXME: There should be a constant for True/False
196+
core::LLVMIsGlobalConstant(self.into()) == 1
197+
}
198+
}
199+
}
200+
201+
/// An alias to another global
202+
pub struct Alias;
203+
native_ref!(&Alias = LLVMValueRef);
204+
impl Deref for Alias {
205+
type Target = GlobalValue;
206+
fn deref(&self) -> &GlobalValue {
207+
unsafe { mem::transmute(self) }
208+
}
209+
}
210+
impl CastFrom for Alias {
211+
type From = Value;
212+
fn cast<'a>(val: &'a Value) -> Option<&'a Alias> {
213+
unsafe {
214+
let alias = mem::transmute(core::LLVMIsAGlobalAlias(val.into()));
215+
util::ptr_to_null(alias)
216+
}
217+
}
218+
}
219+
112220
/// A function that can be called and contains blocks.
113221
pub struct Function;
114222
native_ref!(&Function = LLVMValueRef);
115223
impl Deref for Function {
116-
type Target = Value;
117-
fn deref(&self) -> &Value {
224+
type Target = GlobalValue;
225+
fn deref(&self) -> &GlobalValue {
118226
unsafe { mem::transmute(self) }
119227
}
120228
}
@@ -279,6 +387,45 @@ impl From<Attribute> for LLVMAttribute {
279387
unsafe { mem::transmute(attr) }
280388
}
281389
}
390+
391+
/// A way of indicating to LLVM how you want a global to interact during linkage.
392+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
393+
#[repr(C)]
394+
pub enum Linkage {
395+
/// Default linkage. The global is externally visible and participates in linkage normally.
396+
External = 0,
397+
/// Never emitted to the containing module's object file. Used to allow inlining and/or other optimisations to take place, given knowledge of the definition of the global, which is somewhere outside of the module. Otherwise the same as LinkOnceODR. Only allowed on definitions, not declarations.
398+
AvailableExternally = 1,
399+
/// Merged with other globals of the same name during linkage. Unreferenced LinkOnce globals may be discarded.
400+
LinkOnceAny = 2,
401+
/// Similar to LinkOnceAny, but indicates that it will only be merged with equivalent globals.
402+
LinkOnceODR = 3,
403+
/// Same merging semantics as LinkOnceAny. Unlike LinkOnce, unreference globals will not be discarded.
404+
WeakAny = 5,
405+
/// Similar to WeakAny, but indicates that it will only be merged with equivalent globals.
406+
WeakODR = 6,
407+
/// Only allowed on global array pointers. When two globals with Appending linkage are merged, they are appended together.
408+
Appending = 7,
409+
/// Similar to Private, but shows as a local symbol in the object file.
410+
Internal = 8,
411+
/// Only directly accessible by objects in the current module. May be renamed as neccessary to avoid collisions, and all references will be updated. Will not show up in the object file's symbol table.
412+
Private = 9,
413+
/// Weak until linked. If not linked, the output symbol is null, instead of undefined.
414+
ExternalWeak = 12,
415+
/// Similar to Weak, but may not have an explicit section, must have a zero initializer, and may not be marked constant. Cannot be used on functions or aliases.
416+
Common = 14,
417+
}
418+
impl From<LLVMLinkage> for Linkage {
419+
fn from(attr: LLVMLinkage) -> Linkage {
420+
unsafe { mem::transmute(attr) }
421+
}
422+
}
423+
impl From<Linkage> for LLVMLinkage {
424+
fn from(attr: Linkage) -> LLVMLinkage {
425+
unsafe { mem::transmute(attr) }
426+
}
427+
}
428+
282429
impl GetContext for Value {
283430
fn get_context(&self) -> &Context {
284431
self.get_type().get_context()

0 commit comments

Comments
 (0)