Skip to content

Commit 690f68c

Browse files
authored
Merge pull request rust-lang#205 from dotconnor/add-call-asm
Add call asm
2 parents c38c6cd + 945a160 commit 690f68c

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

src/context.rs

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
use llvm_sys::core::{LLVMAppendBasicBlockInContext, LLVMContextCreate, LLVMContextDispose, LLVMCreateBuilderInContext, LLVMDoubleTypeInContext, LLVMFloatTypeInContext, LLVMFP128TypeInContext, LLVMInsertBasicBlockInContext, LLVMInt16TypeInContext, LLVMInt1TypeInContext, LLVMInt32TypeInContext, LLVMInt64TypeInContext, LLVMInt8TypeInContext, LLVMIntTypeInContext, LLVMModuleCreateWithNameInContext, LLVMStructCreateNamed, LLVMStructTypeInContext, LLVMVoidTypeInContext, LLVMHalfTypeInContext, LLVMGetGlobalContext, LLVMPPCFP128TypeInContext, LLVMConstStructInContext, LLVMMDNodeInContext, LLVMMDStringInContext, LLVMGetMDKindIDInContext, LLVMX86FP80TypeInContext, LLVMConstStringInContext, LLVMContextSetDiagnosticHandler};
44
#[llvm_versions(4.0..=latest)]
55
use llvm_sys::core::{LLVMCreateEnumAttribute, LLVMCreateStringAttribute};
6+
#[llvm_versions(3.6..7.0)]
7+
use llvm_sys::core::{LLVMConstInlineAsm};
8+
#[llvm_versions(7.0..=latest)]
9+
use llvm_sys::core::{LLVMGetInlineAsm};
10+
#[llvm_versions(7.0..=latest)]
11+
use crate::InlineAsmDialect;
612
use llvm_sys::prelude::{LLVMContextRef, LLVMTypeRef, LLVMValueRef, LLVMDiagnosticInfoRef};
713
use llvm_sys::ir_reader::LLVMParseIRInContext;
814
use llvm_sys::target::{LLVMIntPtrTypeForASInContext, LLVMIntPtrTypeInContext};
@@ -19,8 +25,8 @@ use crate::memory_buffer::MemoryBuffer;
1925
use crate::module::Module;
2026
use crate::support::{to_c_str, LLVMString};
2127
use crate::targets::TargetData;
22-
use crate::types::{BasicTypeEnum, FloatType, IntType, StructType, VoidType, AsTypeRef};
23-
use crate::values::{AsValueRef, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, StructValue, MetadataValue, VectorValue};
28+
use crate::types::{BasicTypeEnum, FloatType, IntType, StructType, VoidType, AsTypeRef, FunctionType};
29+
use crate::values::{AsValueRef, BasicMetadataValueEnum, BasicValueEnum, FunctionValue, StructValue, MetadataValue, VectorValue, PointerValue};
2430

2531
use std::marker::PhantomData;
2632
use std::mem::{forget, ManuallyDrop};
@@ -191,6 +197,76 @@ impl Context {
191197
Err(LLVMString::new(err_str))
192198
}
193199

200+
/// Creates a inline asm function pointer.
201+
///
202+
/// # Example
203+
/// ```no_run
204+
/// use inkwell::context::Context;
205+
///
206+
/// let context = Context::create();
207+
/// let module = context.create_module("my_module");
208+
/// let builder = context.create_builder();
209+
/// let void_type = context.void_type();
210+
/// let fn_type = void_type.fn_type(&[], false);
211+
/// let fn_val = module.add_function("my_fn", fn_type, None);
212+
/// let basic_block = context.append_basic_block(fn_val, "entry");
213+
///
214+
/// builder.position_at_end(basic_block);
215+
/// let asm_fn = context.i64_type().fn_type(&[context.i64_type().into(), context.i64_type().into()], false);
216+
/// let asm = context.create_inline_asm(asm_fn, "syscall".to_string(), "=r,{rax},{rdi}".to_string(), true, false, None);
217+
/// let params = &[context.i64_type().const_int(60, false).into(), context.i64_type().const_int(1, false).into()];
218+
/// builder.build_call(asm, params, "exit");
219+
/// builder.build_return(None);
220+
#[llvm_versions(7.0..=latest)]
221+
pub fn create_inline_asm(&self, ty: FunctionType, mut assembly: String, mut constraints: String, sideeffects: bool, alignstack: bool, dialect: Option<InlineAsmDialect>) -> PointerValue {
222+
let value = unsafe {
223+
LLVMGetInlineAsm(
224+
ty.as_type_ref(),
225+
assembly.as_mut_ptr() as *mut ::libc::c_char,
226+
assembly.len(),
227+
constraints.as_mut_ptr() as *mut ::libc::c_char,
228+
constraints.len(),
229+
sideeffects as i32,
230+
alignstack as i32,
231+
dialect.unwrap_or(InlineAsmDialect::ATT).into()
232+
)
233+
};
234+
PointerValue::new(value)
235+
}
236+
/// Creates a inline asm function pointer.
237+
///
238+
/// # Example
239+
/// ```no_run
240+
/// use inkwell::context::Context;
241+
///
242+
/// let context = Context::create();
243+
/// let module = context.create_module("my_module");
244+
/// let builder = context.create_builder();
245+
/// let void_type = context.void_type();
246+
/// let fn_type = void_type.fn_type(&[], false);
247+
/// let fn_val = module.add_function("my_fn", fn_type, None);
248+
/// let basic_block = context.append_basic_block(fn_val, "entry");
249+
///
250+
/// builder.position_at_end(basic_block);
251+
/// let asm_fn = context.i64_type().fn_type(&[context.i64_type().into(), context.i64_type().into()], false);
252+
/// let asm = context.create_inline_asm(asm_fn, "syscall".to_string(), "=r,{rax},{rdi}".to_string(), true, false);
253+
/// let params = &[context.i64_type().const_int(60, false).into(), context.i64_type().const_int(1, false).into()];
254+
/// builder.build_call(asm, params, "exit");
255+
/// builder.build_return(None);
256+
#[llvm_versions(3.6..7.0)]
257+
pub fn create_inline_asm(&self, ty: FunctionType, mut assembly: String, mut constraints: String, sideeffects: bool, alignstack: bool) -> PointerValue {
258+
let value = unsafe {
259+
LLVMConstInlineAsm(
260+
ty.as_type_ref(),
261+
assembly.as_ptr() as *const ::libc::c_char,
262+
constraints.as_ptr() as *const ::libc::c_char,
263+
sideeffects as i32,
264+
alignstack as i32
265+
)
266+
};
267+
PointerValue::new(value)
268+
}
269+
194270
/// Gets the `VoidType`. It will be assigned the current context.
195271
///
196272
/// # Example

src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub mod values;
4141

4242
use llvm_sys::{LLVMIntPredicate, LLVMRealPredicate, LLVMVisibility, LLVMThreadLocalMode, LLVMDLLStorageClass, LLVMAtomicOrdering, LLVMAtomicRMWBinOp};
4343

44+
#[llvm_versions(7.0..=latest)]
45+
use llvm_sys::LLVMInlineAsmDialect;
46+
4447
use std::convert::TryFrom;
4548

4649
// Thanks to kennytm for coming up with assert_unique_features!
@@ -385,3 +388,13 @@ impl Default for DLLStorageClass {
385388
DLLStorageClass::Default
386389
}
387390
}
391+
392+
#[llvm_versions(7.0..=latest)]
393+
#[llvm_enum(LLVMInlineAsmDialect)]
394+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
395+
pub enum InlineAsmDialect {
396+
#[llvm_variant(LLVMInlineAsmDialectATT)]
397+
ATT,
398+
#[llvm_variant(LLVMInlineAsmDialectIntel)]
399+
Intel,
400+
}

0 commit comments

Comments
 (0)