|
1 | 1 | use libc::{c_char, c_uint, c_int};
|
2 | 2 | use ffi::prelude::LLVMValueRef;
|
3 | 3 | use ffi::{core, LLVMAttribute};
|
| 4 | +use ffi::LLVMLinkage; |
4 | 5 | use std::ffi::CString;
|
5 | 6 | use std::{fmt, mem};
|
6 | 7 | use std::ops::{Deref, Index};
|
@@ -109,12 +110,119 @@ impl Arg {
|
109 | 110 | unsafe { core::LLVMRemoveAttribute(self.into(), attr.into()) }
|
110 | 111 | }
|
111 | 112 | }
|
| 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 | + |
112 | 220 | /// A function that can be called and contains blocks.
|
113 | 221 | pub struct Function;
|
114 | 222 | native_ref!(&Function = LLVMValueRef);
|
115 | 223 | impl Deref for Function {
|
116 |
| - type Target = Value; |
117 |
| - fn deref(&self) -> &Value { |
| 224 | + type Target = GlobalValue; |
| 225 | + fn deref(&self) -> &GlobalValue { |
118 | 226 | unsafe { mem::transmute(self) }
|
119 | 227 | }
|
120 | 228 | }
|
@@ -279,6 +387,45 @@ impl From<Attribute> for LLVMAttribute {
|
279 | 387 | unsafe { mem::transmute(attr) }
|
280 | 388 | }
|
281 | 389 | }
|
| 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 | + |
282 | 429 | impl GetContext for Value {
|
283 | 430 | fn get_context(&self) -> &Context {
|
284 | 431 | self.get_type().get_context()
|
|
0 commit comments