diff options
| author | Andrei Homescu <ah@immunant.com> | 2019-03-25 14:28:03 -0700 |
|---|---|---|
| committer | Andrei Homescu <ah@immunant.com> | 2019-06-17 16:04:49 -0700 |
| commit | b9ea653aee231114acbe6d4b3c7b1d692772d060 (patch) | |
| tree | eceeeff8ba9582d6fb956358c1dc06eceadb2a29 /src/librustc_codegen_ssa | |
| parent | 70456a6cbd67c0547d22997007afaaed0819767e (diff) | |
| download | rust-b9ea653aee231114acbe6d4b3c7b1d692772d060.tar.gz rust-b9ea653aee231114acbe6d4b3c7b1d692772d060.zip | |
Expose `VaListImpl` as the Rust equivalent of `__va_list_tag` and implement Clone for it.
Diffstat (limited to 'src/librustc_codegen_ssa')
| -rw-r--r-- | src/librustc_codegen_ssa/mir/block.rs | 6 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/mir/mod.rs | 33 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/traits/intrinsic.rs | 4 |
3 files changed, 16 insertions, 27 deletions
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index e4b82d84966..cee9c9009a2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -503,7 +503,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - // The "spoofed" `VaList` added to a C-variadic functions signature + // The "spoofed" `VaListImpl` added to a C-variadic functions signature // should not be included in the `extra_args` calculation. let extra_args_start_idx = sig.inputs().len() - if sig.c_variadic { 1 } else { 0 }; let extra_args = &args[extra_args_start_idx..]; @@ -687,7 +687,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (&args[..], None) }; - // Useful determining if the current argument is the "spoofed" `VaList` + // Useful determining if the current argument is the "spoofed" `VaListImpl` let last_arg_idx = if sig.inputs().is_empty() { None } else { @@ -695,7 +695,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; 'make_args: for (i, arg) in first_args.iter().enumerate() { // If this is a C-variadic function the function signature contains - // an "spoofed" `VaList`. This argument is ignored, but we need to + // an "spoofed" `VaListImpl`. This argument is ignored, but we need to // populate it with a dummy operand so that the users real arguments // are not overwritten. let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index dd69d358313..df3823dd9ca 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -83,7 +83,7 @@ pub struct FunctionCx<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> { scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<Bx::DIScope>>, /// If this function is a C-variadic function, this contains the `PlaceRef` of the - /// "spoofed" `VaList`. + /// "spoofed" `VaListImpl`. va_list_ref: Option<PlaceRef<'tcx, Bx::Value>>, } @@ -561,35 +561,24 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( indirect_operand.store(bx, tmp); tmp } else { + let tmp = PlaceRef::alloca(bx, arg.layout, &name); if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) { - let va_list_impl = match arg_decl.ty.ty_adt_def() { - Some(adt) => adt.non_enum_variant(), - None => bug!("`va_list` language item improperly constructed") + let va_list_did = match tcx.lang_items().va_list() { + Some(did) => did, + None => bug!("`va_list` lang item required for C-variadic functions"), }; - match tcx.type_of(va_list_impl.fields[0].did).sty { - ty::Ref(_, ty, _) => { - // If the underlying structure the `VaList` contains is a structure, - // we need to allocate it (e.g., X86_64 on Linux). - let tmp = PlaceRef::alloca(bx, arg.layout, &name); - if let ty::Adt(..) = ty.sty { - let layout = bx.layout_of(ty); - // Create an unnamed allocation for the backing structure - // and store it in the the spoofed `VaList`. - let backing = PlaceRef::alloca(bx, layout, ""); - bx.store(backing.llval, tmp.llval, layout.align.abi); - } - // Call `va_start` on the spoofed `VaList`. + match arg_decl.ty.sty { + ty::Adt(def, _) if def.did == va_list_did => { + // Call `va_start` on the spoofed `VaListImpl`. bx.va_start(tmp.llval); *va_list_ref = Some(tmp); - tmp - } - _ => bug!("improperly constructed `va_list` lang item"), + }, + _ => bug!("last argument of variadic function is not a `va_list`") } } else { - let tmp = PlaceRef::alloca(bx, arg.layout, &name); bx.store_fn_arg(arg, &mut llarg_idx, tmp); - tmp } + tmp }; let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use; arg_scope.map(|scope| { diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index cd527898977..ede30a0bed7 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -20,10 +20,10 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; - /// Trait method used to inject `va_start` on the "spoofed" `VaList` in + /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in /// Rust defined C-variadic functions. fn va_start(&mut self, val: Self::Value) -> Self::Value; - /// Trait method used to inject `va_end` on the "spoofed" `VaList` before + /// Trait method used to inject `va_end` on the "spoofed" `VaListImpl` before /// Rust defined C-variadic functions return. fn va_end(&mut self, val: Self::Value) -> Self::Value; } |
