Skip to content

Commit 638ff83

Browse files
committed
Add intrinsics for va_list
Add the llvm intrinsics used to manipulate a va_list and add the va_list method to Type that builds a va_list according to the targets va_list_kind.
1 parent c123559 commit 638ff83

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

src/libcore/intrinsics.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1398,4 +1398,22 @@ extern "rust-intrinsic" {
13981398
/// Emits a `!nontemporal` store according to LLVM (see their docs).
13991399
/// Probably will never become stable.
14001400
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
1401+
1402+
/// Initialize the arglist `ap` for processing via `va_arg`.
1403+
#[cfg(not(stage0))]
1404+
pub fn va_start(ap: *mut i8);
1405+
1406+
/// Destroy the arglist `ap` after initialization with `va_start` or
1407+
/// `va_copy`.
1408+
#[cfg(not(stage0))]
1409+
pub fn va_end(ap: *mut i8);
1410+
1411+
/// Copy the current location of arglist `ap0` to the arglist `ap1`.
1412+
#[cfg(not(stage0))]
1413+
pub fn va_copy(ap0: *const i8, ap1: *mut i8);
1414+
1415+
/// Loads an argument of type `T` from the `va_list` `ap` and increment the
1416+
/// argument `ap` points to.
1417+
#[cfg(not(stage0))]
1418+
pub fn va_arg<T: Copy>(ap: *mut i8) -> T;
14011419
}

src/librustc_trans/context.rs

+5
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,11 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
650650
ifn!("llvm.assume", fn(i1) -> void);
651651
ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
652652

653+
// variadic intrinsics
654+
ifn!("llvm.va_start", fn(i8p) -> void);
655+
ifn!("llvm.va_end", fn(i8p) -> void);
656+
ifn!("llvm.va_copy", fn(i8p, i8p) -> void);
657+
653658
if cx.sess().opts.debuginfo != NoDebugInfo {
654659
ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void);
655660
ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void);

src/librustc_trans/intrinsic.rs

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
7777
"roundf64" => "llvm.round.f64",
7878
"assume" => "llvm.assume",
7979
"abort" => "llvm.trap",
80+
"va_start" => "llvm.va_start",
81+
"va_copy" => "llvm.va_copy",
82+
"va_end" => "llvm.va_end",
8083
_ => return None
8184
};
8285
Some(cx.get_intrinsic(&llvm_name))
@@ -138,6 +141,9 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
138141
let llfn = cx.get_intrinsic(&("llvm.debugtrap"));
139142
bx.call(llfn, &[], None)
140143
}
144+
"va_arg" => {
145+
bx.va_arg(args[0].immediate(), llret_ty)
146+
}
141147
"size_of" => {
142148
let tp_ty = substs.type_at(0);
143149
C_usize(cx, cx.size_of(tp_ty).bytes())

src/librustc_trans/type_.rs

+31
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use context::CodegenCx;
1818

1919
use syntax::ast;
2020
use rustc::ty::layout::{self, Align, Size};
21+
use rustc_back::VaListKind;
2122

2223
use std::ffi::CString;
2324
use std::fmt;
@@ -297,4 +298,34 @@ impl Type {
297298
pub fn x86_mmx(cx: &CodegenCx) -> Type {
298299
ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx))
299300
}
301+
302+
pub fn va_list(cx: &CodegenCx, name: &str) -> Type {
303+
let int_t = Type::c_int(cx);
304+
let voidp_t = Type::i8p(cx);
305+
match cx.tcx.sess.target.target.options.va_list_kind {
306+
VaListKind::CharPtr => {
307+
Type::i8p(cx)
308+
},
309+
VaListKind::VoidPtr => {
310+
voidp_t
311+
},
312+
VaListKind::X86_64Abi => {
313+
let mut va_list_t = Type::named_struct(cx, name);
314+
va_list_t.set_struct_body(&[int_t, int_t, voidp_t, voidp_t], false);
315+
va_list_t
316+
},
317+
VaListKind::AArch64Abi => {
318+
let mut va_list_t = Type::named_struct(cx, name);
319+
va_list_t.set_struct_body(&[voidp_t, voidp_t, voidp_t, int_t, int_t], false);
320+
va_list_t
321+
},
322+
VaListKind::PowerPcAbi => {
323+
let i8_t = Type::i8(cx);
324+
let i16_t = Type::i16(cx);
325+
let mut va_list_t = Type::named_struct(cx, name);
326+
va_list_t.set_struct_body(&[i8_t, i8_t, i16_t, voidp_t, voidp_t], false);
327+
va_list_t
328+
},
329+
}
330+
}
300331
}

src/librustc_typeck/check/intrinsic.rs

+8
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
319319
(0, vec![ptr_ty, tcx.types.usize], tcx.types.usize)
320320
},
321321

322+
"va_start" | "va_end" => (0, vec![tcx.mk_mut_ptr(tcx.types.i8)], tcx.mk_nil()),
323+
324+
"va_copy" => {
325+
(0, vec![tcx.mk_imm_ptr(tcx.types.i8), tcx.mk_mut_ptr(tcx.types.i8)], tcx.mk_nil())
326+
}
327+
328+
"va_arg" => (1, vec![tcx.mk_mut_ptr(tcx.types.i8)], param(0)),
329+
322330
"nontemporal_store" => {
323331
(1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil())
324332
}

0 commit comments

Comments
 (0)