Skip to content

Commit 5c7bc8b

Browse files
committed
Merge pull request TomBebbington#7 from HeroesGrave/master
Implement more functionality for globals + more
2 parents cab7993 + fcc4937 commit 5c7bc8b

File tree

8 files changed

+204
-33
lines changed

8 files changed

+204
-33
lines changed

Cargo.lock

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use ffi::core;
22
use ffi::prelude::LLVMBasicBlockRef;
3-
use value::Value;
3+
use value::Function;
44
use util;
55

66
/// A container of instructions that execute sequentially.
77
pub struct BasicBlock;
88
native_ref!(&BasicBlock = LLVMBasicBlockRef);
99
impl BasicBlock {
1010
/// Return the enclosing method, or `None` if it is not attached to a method.
11-
pub fn get_parent(&self) -> Option<&Value> {
11+
pub fn get_parent(&self) -> Option<&Function> {
1212
unsafe { util::ptr_to_null(core::LLVMGetBasicBlockParent(self.into())) }
1313
}
1414
/// Move this basic block after the `other` basic block in its function.

src/builder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ impl Builder {
119119
pub fn build_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> &Value {
120120
unsafe { core::LLVMBuildInsertValue(self.into(), agg.into(), elem.into(), index as c_uint, NULL_NAME.as_ptr()).into() }
121121
}
122+
/// Build an instruction that extracts a value from an aggregate data value.
123+
pub fn build_extract_value(&self, agg: &Value, index: usize) -> &Value {
124+
unsafe { core::LLVMBuildExtractValue(self.into(), agg.into(), index as c_uint, NULL_NAME.as_ptr()).into() }
125+
}
122126
/// Build an instruction that computes the address of a subelement of an aggregate data structure.
123127
///
124128
/// Basically type-safe pointer arithmetic.

src/engine.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use value::{Function, Value};
1717
/// An abstract interface for implementation execution of LLVM modules.
1818
///
1919
/// This is designed to support both interpreter and just-in-time (JIT) compiler implementations.
20-
pub trait ExecutionEngine<'a, 'b:'a> where LLVMExecutionEngineRef:From<&'b Self> {
20+
pub trait ExecutionEngine<'a, 'b:'a>:Sized+'b where LLVMExecutionEngineRef:From<&'b Self> {
2121
/// The options given to the engine upon creation.
2222
type Options : Copy;
2323
/// Create a new execution engine with the given `Module` and options, or return a
@@ -130,9 +130,9 @@ impl<'a, 'b> JitEngine<'a> {
130130
mem::transmute(ptr)
131131
}
132132
}
133-
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for JitEngine<'a> {
133+
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for JitEngine<'b> {
134134
type Options = JitOptions;
135-
fn new(module: &'a Module, options: JitOptions) -> Result<JitEngine<'a>, CBox<str>> {
135+
fn new(module: &'a Module, options: JitOptions) -> Result<JitEngine<'b>, CBox<str>> {
136136
unsafe {
137137
let mut ee = mem::uninitialized();
138138
let mut out = mem::zeroed();
@@ -176,9 +176,9 @@ impl<'a> Interpreter<'a> {
176176
unsafe { engine::LLVMRunFunction(self.into(), function.into(), args.len() as c_uint, ptr).into() }
177177
}
178178
}
179-
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for Interpreter<'a> {
179+
impl<'a, 'b:'a> ExecutionEngine<'a, 'b> for Interpreter<'b> {
180180
type Options = ();
181-
fn new(module: &'a Module, _: ()) -> Result<Interpreter<'a>, CBox<str>> {
181+
fn new(module: &'a Module, _: ()) -> Result<Interpreter<'b>, CBox<str>> {
182182
unsafe {
183183
let mut ee = mem::uninitialized();
184184
let mut out = mem::zeroed();

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::{Alias, 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/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ impl Type {
3535
unsafe { core::LLVMPointerType(elem.into(), 0 as c_uint) }.into()
3636
}
3737
/// Make a new structure type with the given types.
38-
pub fn new_struct<'a>(elems: &[&'a Type], packed: bool) -> &'a Type {
39-
unsafe { core::LLVMStructType(elems.as_ptr() as *mut LLVMTypeRef, elems.len() as c_uint, packed as c_int) }.into()
38+
pub fn new_struct<'a>(context:&'a Context, elems: &[&'a Type], packed: bool) -> &'a Type {
39+
unsafe { core::LLVMStructTypeInContext(context.into(), elems.as_ptr() as *mut LLVMTypeRef, elems.len() as c_uint, packed as c_int) }.into()
4040
}
4141
/// Returns true if the size of the type is known at compile-time.
4242
///

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)