Skip to content

Commit 8c7dcf9

Browse files
Grégoire GeisTheDan64
Grégoire Geis
authored andcommitted
Improvements to documentation (rust-lang#20)
* Improvements to documentation * Improved style a bit more * Merged OptimizationLevel and CodeGenOptLevel, among other things * Option<OptimizationLevel> -> OptimizationLevel with Default
1 parent d835d33 commit 8c7dcf9

11 files changed

+144
-61
lines changed

examples/kaleidoscope/main.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use self::inkwell::passes::PassManager;
2929
use self::inkwell::targets::{InitializationConfig, Target};
3030
use self::inkwell::types::BasicType;
3131
use self::inkwell::values::{BasicValue, FloatValue, FunctionValue, PointerValue};
32-
use self::inkwell::FloatPredicate;
32+
use self::inkwell::{OptimizationLevel, FloatPredicate};
3333

3434
use Token::*;
3535

@@ -98,7 +98,6 @@ impl<'a> Lexer<'a> {
9898
}
9999

100100
/// Lexes and returns the next `Token` from the source code.
101-
#[allow(unused_variables)]
102101
pub fn lex(&mut self) -> LexResult {
103102
let chars = self.chars.deref_mut();
104103
let src = self.input;
@@ -157,12 +156,12 @@ impl<'a> Lexer<'a> {
157156
Ok(Token::Comment)
158157
},
159158

160-
ch @ '.' | ch @ '0' ... '9' => {
159+
'.' | '0' ... '9' => {
161160
// Parse number literal
162161
loop {
163162
let ch = match chars.peek() {
164163
Some(ch) => *ch,
165-
None => { return Ok(Token::EOF); }
164+
None => return Ok(Token::EOF)
166165
};
167166

168167
// Parse float.
@@ -182,7 +181,7 @@ impl<'a> Lexer<'a> {
182181
loop {
183182
let ch = match chars.peek() {
184183
Some(ch) => *ch,
185-
None => { return Ok(Token::EOF); }
184+
None => return Ok(Token::EOF)
186185
};
187186

188187
// A word-like identifier only contains underscores and alphanumeric characters.
@@ -1341,7 +1340,7 @@ pub fn main() {
13411340
};
13421341

13431342
if is_anonymous {
1344-
let ee = module.create_jit_execution_engine(0).unwrap();
1343+
let ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
13451344

13461345
let addr = match ee.get_function_address(name.as_str()) {
13471346
Ok(addr) => addr,

src/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ pub struct ContextRef {
349349
}
350350

351351
impl ContextRef {
352-
pub fn new(context: Context) -> Self {
352+
pub(crate) fn new(context: Context) -> Self {
353353
ContextRef {
354354
context: Some(context),
355355
}

src/lib.rs

+21
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,27 @@ impl FloatPredicate {
125125
}
126126
}
127127

128+
129+
/// Defines the optimization level used to compile a `Module`.
130+
///
131+
/// # Remarks
132+
/// See also: http://llvm.org/doxygen/CodeGen_8h_source.html
133+
#[repr(u32)]
134+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
135+
pub enum OptimizationLevel {
136+
None = 0,
137+
Less = 1,
138+
Default = 2,
139+
Aggressive = 3
140+
}
141+
142+
impl Default for OptimizationLevel {
143+
/// Returns the default value for `OptimizationLevel`, namely `OptimizationLevel::Default`.
144+
fn default() -> Self {
145+
OptimizationLevel::Default
146+
}
147+
}
148+
128149
// REVIEW: Maybe this belongs in some sort of prelude?
129150
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
130151
pub enum GlobalVisibility {

src/module.rs

+90-11
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ use std::mem::{forget, uninitialized, zeroed};
1111
use std::path::Path;
1212
use std::slice::from_raw_parts;
1313

14+
use OptimizationLevel;
1415
use context::{Context, ContextRef};
1516
use data_layout::DataLayout;
1617
use execution_engine::ExecutionEngine;
1718
use memory_buffer::MemoryBuffer;
1819
use types::{AsTypeRef, BasicType, FunctionType, BasicTypeEnum};
19-
use values::{AsValueRef, BasicValue, FunctionValue, GlobalValue, MetadataValue};
20+
use values::{AsValueRef, FunctionValue, GlobalValue, MetadataValue};
2021

2122
// REVIEW: Maybe this should go into it's own module?
2223
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -40,6 +41,19 @@ pub enum Linkage {
4041
WeakODRLinkage,
4142
}
4243

44+
/// Defines the address space in which a global will be inserted.
45+
///
46+
/// # Remarks
47+
/// See also: http://llvm.org/doxygen/NVPTXBaseInfo_8h_source.html
48+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
49+
pub enum AddressSpace {
50+
Generic = 0,
51+
Global = 1,
52+
Shared = 3,
53+
Const = 4,
54+
Local = 5
55+
}
56+
4357
impl Linkage {
4458
pub(crate) fn new(linkage: LLVMLinkage) -> Self {
4559
match linkage {
@@ -86,6 +100,8 @@ impl Linkage {
86100
}
87101
}
88102

103+
/// Represents a reference to an LLVM `Module`.
104+
/// The underlying module will be disposed when dropping this object.
89105
#[derive(Debug, PartialEq, Eq)]
90106
pub struct Module {
91107
pub(crate) module: LLVMModuleRef,
@@ -129,12 +145,31 @@ impl Module {
129145
Module::new(module)
130146
}
131147

132-
// TODOC: LLVM will default linkage to ExternalLinkage (at least in 3.7)
133-
pub fn add_function(&self, name: &str, return_type: &FunctionType, linkage: Option<&Linkage>) -> FunctionValue {
148+
/// Creates a function given its `name` and `ty`, adds it to the `Module`
149+
/// and returns it.
150+
///
151+
/// An optional `linkage` can be specified, without which the default value
152+
/// `Linkage::ExternalLinkage` will be used.
153+
///
154+
/// # Example
155+
/// ```
156+
/// use inkwell::context::Context;
157+
/// use inkwell::module::{Module, Linkage};
158+
///
159+
/// let context = Context::get_global();
160+
/// let module = Module::create("my_module");
161+
///
162+
/// let fn_type = context.f32_type().fn_type(&[], false);
163+
/// let fn_val = module.add_function("my_function", &fn_type, None);
164+
///
165+
/// assert_eq!(fn_val.get_name().to_str(), Ok("my_function"));
166+
/// assert_eq!(fn_val.get_linkage(), Linkage::ExternalLinkage);
167+
/// ```
168+
pub fn add_function(&self, name: &str, ty: &FunctionType, linkage: Option<&Linkage>) -> FunctionValue {
134169
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
135170

136171
let value = unsafe {
137-
LLVMAddFunction(self.module, c_string.as_ptr(), return_type.as_type_ref())
172+
LLVMAddFunction(self.module, c_string.as_ptr(), ty.as_type_ref())
138173
};
139174

140175
if let Some(linkage) = linkage {
@@ -146,6 +181,24 @@ impl Module {
146181
FunctionValue::new(value).expect("add_function should always succeed in adding a new function")
147182
}
148183

184+
/// Gets the `Context` from which this `Module` originates.
185+
///
186+
/// # Example
187+
/// ```
188+
/// use inkwell::context::{Context, ContextRef};
189+
/// use inkwell::module::Module;
190+
///
191+
/// let global_context = Context::get_global();
192+
/// let global_module = Module::create("my_global_module");
193+
///
194+
/// assert_eq!(global_module.get_context(), global_context);
195+
///
196+
/// let local_context = Context::create();
197+
/// let local_module = local_context.create_module("my_module");
198+
///
199+
/// assert_eq!(*local_module.get_context(), local_context);
200+
/// assert_ne!(local_context, *global_context);
201+
/// ```
149202
pub fn get_context(&self) -> ContextRef {
150203
let context = unsafe {
151204
LLVMGetModuleContext(self.module)
@@ -210,15 +263,29 @@ impl Module {
210263
}
211264
}
212265

213-
// TODOC: EE must *own* modules and deal out references
214-
// REVIEW: Looking at LLVM source, opt_level seems to be casted into a targets::CodeGenOptLevel
215-
// or LLVM equivalent anyway
216-
pub fn create_jit_execution_engine(self, opt_level: u32) -> Result<ExecutionEngine, String> {
266+
/// Consumes this `Module`, and creates a JIT `ExecutionEngine` from it.
267+
///
268+
/// # Example
269+
/// ```no_run
270+
/// use inkwell::OptimizationLevel;
271+
/// use inkwell::context::Context;
272+
/// use inkwell::module::Module;
273+
/// use inkwell::targets::{InitializationConfig, Target};
274+
///
275+
/// Target::initialize_native(&InitializationConfig::default()).expect("Failed to initialize native target");
276+
///
277+
/// let context = Context::get_global();
278+
/// let module = Module::create("my_module");
279+
/// let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
280+
///
281+
/// assert_eq!(execution_engine.get_module_at(0).get_context(), context);
282+
/// ```
283+
pub fn create_jit_execution_engine(self, opt_level: OptimizationLevel) -> Result<ExecutionEngine, String> {
217284
let mut execution_engine = unsafe { uninitialized() };
218285
let mut err_str = unsafe { zeroed() };
219286

220287
let code = unsafe {
221-
LLVMCreateJITCompilerForModule(&mut execution_engine, self.module, opt_level, &mut err_str) // Should take ownership of module
288+
LLVMCreateJITCompilerForModule(&mut execution_engine, self.module, opt_level as u32, &mut err_str) // Should take ownership of module
222289
};
223290

224291
if code == 1 {
@@ -240,12 +307,12 @@ impl Module {
240307
Ok(execution_engine)
241308
}
242309

243-
pub fn add_global(&self, type_: &BasicType, address_space: Option<u32>, name: &str) -> GlobalValue {
310+
pub fn add_global(&self, type_: &BasicType, address_space: Option<AddressSpace>, name: &str) -> GlobalValue {
244311
let c_string = CString::new(name).expect("Conversion to CString failed unexpectedly");
245312

246313
let value = unsafe {
247314
match address_space {
248-
Some(address_space) => LLVMAddGlobalInAddressSpace(self.module, type_.as_type_ref(), c_string.as_ptr(), address_space),
315+
Some(address_space) => LLVMAddGlobalInAddressSpace(self.module, type_.as_type_ref(), c_string.as_ptr(), address_space as u32),
249316
None => LLVMAddGlobal(self.module, type_.as_type_ref(), c_string.as_ptr()),
250317
}
251318
};
@@ -289,7 +356,17 @@ impl Module {
289356
MemoryBuffer::new(memory_buffer)
290357
}
291358

359+
/// Ensures that the current `Module` is valid, and returns a `bool`
360+
/// that describes whether or not it is.
361+
///
362+
/// * `print` - Whether or not a message describing the error should be printed
363+
/// to stderr, in case of failure.
364+
///
365+
/// # Remarks
366+
/// See also: http://llvm.org/doxygen/Analysis_2Analysis_8cpp_source.html
292367
pub fn verify(&self, print: bool) -> bool {
368+
// REVIEW <6A>: Maybe, instead of printing the module to stderr with `print`,
369+
// we should return Result<(), String> that contains an error string?
293370
let mut err_str = unsafe { zeroed() };
294371

295372
let action = if print {
@@ -341,12 +418,14 @@ impl Module {
341418
.set(self.get_raw_data_layout());
342419
}
343420

421+
/// Prints the content of the `Module` to stderr.
344422
pub fn print_to_stderr(&self) {
345423
unsafe {
346424
LLVMDumpModule(self.module);
347425
}
348426
}
349427

428+
/// Prints the content of the `Module` to a string.
350429
pub fn print_to_string(&self) -> &CStr {
351430
unsafe {
352431
CStr::from_ptr(LLVMPrintModuleToString(self.module))

src/passes.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use llvm_sys::transforms::pass_manager_builder::{LLVMPassManagerBuilderRef, LLVM
77
use llvm_sys::transforms::scalar::{LLVMAddAggressiveDCEPass, LLVMAddMemCpyOptPass, LLVMAddBitTrackingDCEPass, LLVMAddAlignmentFromAssumptionsPass, LLVMAddCFGSimplificationPass, LLVMAddDeadStoreEliminationPass, LLVMAddScalarizerPass, LLVMAddMergedLoadStoreMotionPass, LLVMAddGVNPass, LLVMAddIndVarSimplifyPass, LLVMAddInstructionCombiningPass, LLVMAddJumpThreadingPass, LLVMAddLICMPass, LLVMAddLoopDeletionPass, LLVMAddLoopIdiomPass, LLVMAddLoopRotatePass, LLVMAddLoopRerollPass, LLVMAddLoopUnrollPass, LLVMAddLoopUnswitchPass, LLVMAddPartiallyInlineLibCallsPass, LLVMAddLowerSwitchPass, LLVMAddPromoteMemoryToRegisterPass, LLVMAddSCCPPass, LLVMAddScalarReplAggregatesPass, LLVMAddScalarReplAggregatesPassSSA, LLVMAddScalarReplAggregatesPassWithThreshold, LLVMAddSimplifyLibCallsPass, LLVMAddTailCallEliminationPass, LLVMAddConstantPropagationPass, LLVMAddDemoteMemoryToRegisterPass, LLVMAddVerifierPass, LLVMAddCorrelatedValuePropagationPass, LLVMAddEarlyCSEPass, LLVMAddLowerExpectIntrinsicPass, LLVMAddTypeBasedAliasAnalysisPass, LLVMAddScopedNoAliasAAPass, LLVMAddBasicAliasAnalysisPass, LLVMAddReassociatePass};
88
use llvm_sys::transforms::vectorize::{LLVMAddBBVectorizePass, LLVMAddLoopVectorizePass, LLVMAddSLPVectorizePass};
99

10+
use OptimizationLevel;
1011
use module::Module;
11-
use targets::{CodeGenOptLevel, TargetData};
12+
use targets::TargetData;
1213
use values::{AsValueRef, FunctionValue};
1314

1415
// REVIEW: Opt Level might be identical to targets::Option<CodeGenOptLevel>
@@ -34,14 +35,9 @@ impl PassManagerBuilder {
3435
PassManagerBuilder::new(pass_manager_builder)
3536
}
3637

37-
pub fn set_optimization_level(&self, opt_level: Option<&CodeGenOptLevel>) {
38-
let opt_level = match opt_level {
39-
Some(level) => level.as_u32(),
40-
None => 0
41-
};
42-
38+
pub fn set_optimization_level(&self, opt_level: OptimizationLevel) {
4339
unsafe {
44-
LLVMPassManagerBuilderSetOptLevel(self.pass_manager_builder, opt_level)
40+
LLVMPassManagerBuilderSetOptLevel(self.pass_manager_builder, opt_level as u32)
4541
}
4642
}
4743

src/targets.rs

+6-22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use llvm_sys::core::LLVMDisposeMessage;
22
use llvm_sys::target::{LLVMTargetDataRef, LLVMCopyStringRepOfTargetData, LLVMSizeOfTypeInBits, LLVMCreateTargetData, LLVMAddTargetData, LLVMByteOrder, LLVMPointerSize, LLVMByteOrdering, LLVMStoreSizeOfType, LLVMABISizeOfType, LLVMABIAlignmentOfType, LLVMCallFrameAlignmentOfType, LLVMPreferredAlignmentOfType, LLVMPreferredAlignmentOfGlobal, LLVMElementAtOffset, LLVMOffsetOfElement, LLVMDisposeTargetData, LLVMPointerSizeForAS, LLVMIntPtrType, LLVMIntPtrTypeForAS, LLVMIntPtrTypeInContext, LLVMIntPtrTypeForASInContext};
33
use llvm_sys::target_machine::{LLVMGetFirstTarget, LLVMTargetRef, LLVMGetNextTarget, LLVMGetTargetFromName, LLVMGetTargetFromTriple, LLVMGetTargetName, LLVMGetTargetDescription, LLVMTargetHasJIT, LLVMTargetHasTargetMachine, LLVMTargetHasAsmBackend, LLVMTargetMachineRef, LLVMDisposeTargetMachine, LLVMGetTargetMachineTarget, LLVMGetTargetMachineTriple, LLVMSetTargetMachineAsmVerbosity, LLVMCreateTargetMachine, LLVMGetTargetMachineCPU, LLVMGetTargetMachineFeatureString, LLVMGetDefaultTargetTriple, LLVMAddAnalysisPasses, LLVMCodeGenOptLevel, LLVMCodeModel, LLVMRelocMode};
44

5+
use OptimizationLevel;
56
use context::Context;
67
use data_layout::DataLayout;
78
use passes::PassManager;
@@ -13,23 +14,6 @@ use std::ffi::{CStr, CString};
1314
use std::mem::zeroed;
1415
use std::ptr;
1516

16-
#[derive(Debug, PartialEq, Eq)]
17-
pub enum CodeGenOptLevel {
18-
Less,
19-
Default,
20-
Aggressive,
21-
}
22-
23-
impl CodeGenOptLevel {
24-
pub(crate) fn as_u32(&self) -> u32 {
25-
match *self {
26-
CodeGenOptLevel::Less => 1,
27-
CodeGenOptLevel::Default => 2,
28-
CodeGenOptLevel::Aggressive => 3,
29-
}
30-
}
31-
}
32-
3317
#[derive(Debug, PartialEq, Eq)]
3418
pub enum CodeModel {
3519
Default,
@@ -541,15 +525,15 @@ impl Target {
541525
}
542526
}
543527

544-
pub fn create_target_machine(&self, triple: &str, cpu: &str, features: &str, level: Option<CodeGenOptLevel>, reloc_mode: RelocMode, code_model: CodeModel) -> Option<TargetMachine> {
528+
pub fn create_target_machine(&self, triple: &str, cpu: &str, features: &str, level: OptimizationLevel, reloc_mode: RelocMode, code_model: CodeModel) -> Option<TargetMachine> {
545529
let triple = CString::new(triple).expect("Conversion to CString failed unexpectedly");
546530
let cpu = CString::new(cpu).expect("Conversion to CString failed unexpectedly");
547531
let features = CString::new(features).expect("Conversion to CString failed unexpectedly");
548532
let level = match level {
549-
None => LLVMCodeGenOptLevel::LLVMCodeGenLevelNone,
550-
Some(CodeGenOptLevel::Less) => LLVMCodeGenOptLevel::LLVMCodeGenLevelLess,
551-
Some(CodeGenOptLevel::Default) => LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault,
552-
Some(CodeGenOptLevel::Aggressive) => LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive,
533+
OptimizationLevel::None => LLVMCodeGenOptLevel::LLVMCodeGenLevelNone,
534+
OptimizationLevel::Less => LLVMCodeGenOptLevel::LLVMCodeGenLevelLess,
535+
OptimizationLevel::Default => LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault,
536+
OptimizationLevel::Aggressive => LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive,
553537
};
554538
let code_model = match code_model {
555539
CodeModel::Default => LLVMCodeModel::LLVMCodeModelDefault,

tests/test_builder.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
extern crate inkwell;
22

3+
use self::inkwell::OptimizationLevel;
34
use self::inkwell::context::Context;
45
use self::inkwell::builder::Builder;
56
use self::inkwell::targets::{InitializationConfig, Target};
@@ -42,7 +43,7 @@ fn test_null_checked_ptr_ops() {
4243
let context = Context::create();
4344
let module = context.create_module("unsafe");
4445
let builder = context.create_builder();
45-
let execution_engine = module.create_jit_execution_engine(0).unwrap();
46+
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
4647
let module = execution_engine.get_module_at(0);
4748

4849
// Here we're going to create a function that looks roughly like:
@@ -107,7 +108,7 @@ fn test_binary_ops() {
107108
let context = Context::create();
108109
let module = context.create_module("unsafe");
109110
let builder = context.create_builder();
110-
let execution_engine = module.create_jit_execution_engine(0).unwrap();
111+
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
111112
let module = execution_engine.get_module_at(0);
112113

113114
// Here we're going to create an and function which looks roughly like:
@@ -193,7 +194,7 @@ fn test_switch() {
193194
let context = Context::create();
194195
let module = context.create_module("unsafe");
195196
let builder = context.create_builder();
196-
let execution_engine = module.create_jit_execution_engine(0).unwrap();
197+
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
197198
let module = execution_engine.get_module_at(0);
198199

199200
// Here we're going to create a function which looks roughly like:
@@ -253,7 +254,7 @@ fn test_bit_shifts() {
253254
let context = Context::create();
254255
let module = context.create_module("unsafe");
255256
let builder = context.create_builder();
256-
let execution_engine = module.create_jit_execution_engine(0).unwrap();
257+
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
257258
let module = execution_engine.get_module_at(0);
258259

259260
// Here we're going to create a function which looks roughly like:

0 commit comments

Comments
 (0)