Skip to content

Commit 25d52d1

Browse files
authored
Translate va_list references and pointers (#522)
1 parent 933bdee commit 25d52d1

38 files changed

Lines changed: 359 additions & 122 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ bool Converter::VisitRecoveryExpr(clang::RecoveryExpr *expr) {
116116
bool Converter::Convert(clang::QualType qual_type) {
117117
// Catch va_list before desugaring
118118
if (IsVaListType(qual_type)) {
119-
StrCat("VaList");
119+
StrCat("*const VaArg");
120120
return false;
121121
}
122122

@@ -311,7 +311,7 @@ bool Converter::VisitPointerType(clang::PointerType *type) {
311311
}
312312

313313
if (IsVaListType(clang::QualType(type, 0))) {
314-
StrCat("VaList");
314+
StrCat("*const VaArg");
315315
return false;
316316
}
317317

@@ -480,7 +480,8 @@ void Converter::ConvertVaListVarDecl(clang::VarDecl *decl) {
480480
// va_list local variable
481481
StrCat(keyword::kLet);
482482
}
483-
StrCat(keyword_mut_, GetNamedDeclAsString(decl), token::kColon, "VaList");
483+
StrCat(keyword_mut_, GetNamedDeclAsString(decl), token::kColon,
484+
"*const VaArg");
484485
}
485486

486487
bool Converter::NeedsMut(const clang::VarDecl *decl, clang::QualType type,
@@ -1838,8 +1839,7 @@ void Converter::ConvertVariadicArg(clang::Expr *arg) {
18381839

18391840
void Converter::ConvertVAArgCall(clang::CallExpr *expr) {
18401841
if (IsBuiltinVaStart(expr)) {
1841-
StrCat(ToString(expr->getArg(0)->IgnoreImpCasts()),
1842-
"= VaList::new(__args)");
1842+
StrCat(ToString(expr->getArg(0)->IgnoreImpCasts()), "= __args.as_ptr()");
18431843
return;
18441844
}
18451845
if (IsBuiltinVaEnd(expr)) {
@@ -4257,7 +4257,7 @@ std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
42574257

42584258
if (IsVaListType(qual_type)) {
42594259
computed_expr_type_ = ComputedExprType::FreshValue;
4260-
return "VaList::default()";
4260+
return "::std::ptr::null()";
42614261
}
42624262

42634263
if (auto arr = GetArrayDefaultAsString(qual_type); !arr.empty()) {

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ std::string ConverterRefCount::BoxValue(std::string &&str) const {
259259
bool ConverterRefCount::Convert(clang::QualType qual_type) {
260260
// Catch va_list before desugaring
261261
if (IsVaListType(qual_type)) {
262-
StrCat(BoxType("VaList"));
262+
StrCat(BoxType("Ptr<VaArg>"));
263263
return false;
264264
}
265265

@@ -291,7 +291,7 @@ bool ConverterRefCount::VisitReferenceType(clang::ReferenceType *type) {
291291
PushConversionKind push(*this, ConversionKind::Unboxed);
292292
return Convert(ctx_.getPointerType(pointee_type));
293293
}
294-
if (pointee_type->isArrayType()) {
294+
if (pointee_type->isArrayType() && !IsVaListType(pointee_type)) {
295295
// A reference to an array decays straight to a pointer to its first
296296
// element, the same way a by-value array parameter would, instead of
297297
// going through a pointer to the whole boxed array.
@@ -325,7 +325,7 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) {
325325
}
326326

327327
if (IsVaListType(clang::QualType(type, 0))) {
328-
StrCat("VaList");
328+
StrCat("Ptr<VaArg>");
329329
return false;
330330
}
331331

@@ -335,10 +335,11 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) {
335335
}
336336

337337
auto pointee_type = type->getPointeeType();
338-
PushConversionKind push1(*this, ConversionKind::Ptr,
339-
!pointee_type->isArrayType());
338+
bool pointee_is_array =
339+
pointee_type->isArrayType() && !IsVaListType(pointee_type);
340+
PushConversionKind push1(*this, ConversionKind::Ptr, !pointee_is_array);
340341
PushConversionKind push2(*this, ConversionKind::FullRefCount,
341-
pointee_type->isArrayType());
342+
pointee_is_array);
342343
if (pointee_type->isRecordType() &&
343344
abstract_structs_.contains(GetID(pointee_type->getAsRecordDecl()))) {
344345
StrCat("PtrDyn<dyn");
@@ -791,6 +792,10 @@ void ConverterRefCount::EmitFunctionPreamble(clang::FunctionDecl *decl) {
791792
// name_2)'. We want to get the parameters from the definition if possible,
792793
// i.e. name_2.
793794
PushConversionKind push(*this, ConversionKind::FullRefCount);
795+
if (decl->isVariadic()) {
796+
StrCat("let __args: Value<Box<[VaArg]>> = "
797+
"Rc::new(RefCell::new(__args.into()));");
798+
}
794799
auto params = decl->getDefinition() ? decl->getDefinition()->parameters()
795800
: decl->parameters();
796801
for (auto *param : params) {
@@ -853,7 +858,7 @@ void ConverterRefCount::ConvertVaListVarDecl(clang::VarDecl *decl) {
853858
StrCat(keyword::kLet);
854859
}
855860

856-
StrCat(GetNamedDeclAsString(decl), token::kColon, "Value<VaList>");
861+
StrCat(GetNamedDeclAsString(decl), token::kColon, "Value<Ptr<VaArg>>");
857862
}
858863

859864
bool ConverterRefCount::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
@@ -1291,7 +1296,12 @@ void ConverterRefCount::ConvertPrintf(clang::CallExpr *expr) {
12911296
}
12921297

12931298
bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
1294-
if (IsBuiltinVaStart(expr) || IsBuiltinVaEnd(expr) || IsBuiltinVaCopy(expr)) {
1299+
if (IsBuiltinVaStart(expr)) {
1300+
StrCat(ToString(expr->getArg(0)->IgnoreImpCasts()),
1301+
"= __args.as_pointer()");
1302+
return false;
1303+
}
1304+
if (IsBuiltinVaEnd(expr) || IsBuiltinVaCopy(expr)) {
12951305
ConvertVAArgCall(expr);
12961306
return false;
12971307
}
@@ -2471,13 +2481,18 @@ bool ConverterRefCount::VisitVAArgExpr(clang::VAArgExpr *expr) {
24712481
if (auto *cast = clang::dyn_cast<clang::ImplicitCastExpr>(va_list_expr)) {
24722482
va_list_expr = cast->getSubExpr();
24732483
}
2474-
StrCat(ConvertLValue(va_list_expr));
2475-
StrCat(".arg::<");
2484+
auto str = ConvertLValue(va_list_expr);
2485+
std::string arg_type;
24762486
{
24772487
PushConversionKind push(*this, ConversionKind::Unboxed);
2478-
StrCat(ToString(expr->getType()));
2488+
arg_type = ToString(expr->getType());
2489+
}
2490+
if (!pending_deref_.empty()) {
2491+
StrCat(pending_deref_.take(), ".with_mut(|__v| __v.arg::<", arg_type,
2492+
">())");
2493+
} else {
2494+
StrCat(str, ".arg::<", arg_type, ">()");
24792495
}
2480-
StrCat(">()");
24812496
SetFreshType(expr->getType());
24822497
return false;
24832498
}
@@ -2529,7 +2544,7 @@ std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) {
25292544

25302545
if (IsVaListType(qual_type)) {
25312546
computed_expr_type_ = ComputedExprType::FreshValue;
2532-
return BoxValue("VaList::default()");
2547+
return BoxValue("Ptr::<VaArg>::default()");
25332548
}
25342549

25352550
if (auto arr = GetArrayDefaultAsString(qual_type); !arr.empty()) {

‎libcc2rs/src/va_args.rs‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::any::Any;
55
use std::ffi::c_void;
66
use std::rc::Rc;
77

8+
use crate::inc::PrefixInc;
9+
use crate::rc::Ptr;
810
use crate::void::AnyPtr;
911

1012
#[derive(Clone)]
@@ -52,21 +54,27 @@ impl<T: crate::reinterpret::ByteRepr + 'static> From<crate::rc::Ptr<T>> for VaAr
5254
}
5355
}
5456

55-
#[derive(Clone, Copy, Default)]
56-
pub struct VaList<'a> {
57-
args: &'a [VaArg],
58-
pos: usize,
57+
impl crate::reinterpret::ByteRepr for VaArg {}
58+
59+
pub trait VaArgs {
60+
fn arg<T: VaArgGet>(&mut self) -> T;
5961
}
6062

61-
impl<'a> VaList<'a> {
62-
pub fn new(args: &'a [VaArg]) -> Self {
63-
VaList { args, pos: 0 }
63+
impl VaArgs for Ptr<VaArg> {
64+
fn arg<T: VaArgGet>(&mut self) -> T {
65+
let val = self.with(T::get);
66+
self.prefix_inc();
67+
val
6468
}
69+
}
6570

66-
pub fn arg<T: VaArgGet>(&mut self) -> T {
67-
let val = &self.args[self.pos];
68-
self.pos += 1;
69-
T::get(val)
71+
impl VaArgs for *const VaArg {
72+
fn arg<T: VaArgGet>(&mut self) -> T {
73+
unsafe {
74+
let val = T::get(&**self);
75+
*self = self.add(1);
76+
val
77+
}
7078
}
7179
}
7280

‎tests/unit/out/refcount/va_arg_chain.rs‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,24 @@ use std::io::prelude::*;
66
use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
9-
pub fn extract_nth_0(mut n: i32, ap: VaList) -> i32 {
10-
let ap: Value<VaList> = Rc::new(RefCell::new(ap));
9+
pub fn extract_nth_0(mut n: i32, ap: Ptr<VaArg>) -> i32 {
10+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(ap));
1111
let mut i: i32 = 0;
1212
'loop_: while (((i < n) as i32) != 0) {
1313
(*ap.borrow_mut()).arg::<i32>();
1414
i.postfix_inc();
1515
}
1616
return (*ap.borrow_mut()).arg::<i32>();
1717
}
18-
pub fn middle_layer_1(mut n: i32, ap: VaList) -> i32 {
19-
let ap: Value<VaList> = Rc::new(RefCell::new(ap));
18+
pub fn middle_layer_1(mut n: i32, ap: Ptr<VaArg>) -> i32 {
19+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(ap));
2020
return ({ extract_nth_0(n, (*ap.borrow()).clone()) });
2121
}
2222
pub fn top_level_2(n: i32, __args: &[VaArg]) -> i32 {
23+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
2324
let n: Value<i32> = Rc::new(RefCell::new(n));
24-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
25-
(*ap.borrow_mut()) = VaList::new(__args);
25+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
26+
(*ap.borrow_mut()) = __args.as_pointer();
2627
let mut result: i32 = ({ middle_layer_1((*n.borrow()), (*ap.borrow()).clone()) });
2728
return result;
2829
}

‎tests/unit/out/refcount/va_arg_concat.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn sum_ints_0(first: i32, __args: &[VaArg]) -> i32 {
10+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
1011
let first: Value<i32> = Rc::new(RefCell::new(first));
11-
let args: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
12+
let args: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
1213
let mut total: i32 = (*first.borrow());
13-
(*args.borrow_mut()) = VaList::new(__args);
14+
(*args.borrow_mut()) = __args.as_pointer();
1415
let mut val: i32 = 0_i32;
1516
'loop_: while (((({
1617
val = (*args.borrow_mut()).arg::<i32>();

‎tests/unit/out/refcount/va_arg_conditional.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn conditional_log_0(mut verbose: i32, fmt: Ptr<i8>, __args: &[VaArg]) -> i32 {
10+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
1011
let fmt: Value<Ptr<i8>> = Rc::new(RefCell::new(fmt));
1112
if (verbose != 0) {
12-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
13-
(*ap.borrow_mut()) = VaList::new(__args);
13+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
14+
(*ap.borrow_mut()) = __args.as_pointer();
1415
let mut result: i32 = (*ap.borrow_mut()).arg::<i32>();
1516
return result;
1617
}

‎tests/unit/out/refcount/va_arg_copy.rs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn sum_with_copy_0(count: i32, __args: &[VaArg]) -> i32 {
10+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
1011
let count: Value<i32> = Rc::new(RefCell::new(count));
11-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
12-
let aq: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
13-
(*ap.borrow_mut()) = VaList::new(__args);
12+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
13+
let aq: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
14+
(*ap.borrow_mut()) = __args.as_pointer();
1415
(*aq.borrow_mut()) = (*ap.borrow_mut()).clone();
1516
let mut sum1: i32 = 0;
1617
let mut i: i32 = 0;

‎tests/unit/out/refcount/va_arg_fn_ptr.rs‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ pub fn add_2(mut a: i32, mut b: i32) -> i32 {
1616
return (a + b);
1717
}
1818
pub fn apply_unary_3(x: i32, __args: &[VaArg]) -> i32 {
19+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
1920
let x: Value<i32> = Rc::new(RefCell::new(x));
20-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
21-
(*ap.borrow_mut()) = VaList::new(__args);
21+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
22+
(*ap.borrow_mut()) = __args.as_pointer();
2223
let mut fn_: FnPtr<fn(i32) -> i32> = (*ap.borrow_mut()).arg::<FnPtr<fn(i32) -> i32>>();
2324
let mut result: i32 = ({ fn_.call((*x.borrow())) });
2425
return result;
2526
}
2627
pub fn apply_binary_4(mut a: i32, b: i32, __args: &[VaArg]) -> i32 {
28+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
2729
let b: Value<i32> = Rc::new(RefCell::new(b));
28-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
29-
(*ap.borrow_mut()) = VaList::new(__args);
30+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
31+
(*ap.borrow_mut()) = __args.as_pointer();
3032
let mut fn_: FnPtr<fn(i32, i32) -> i32> =
3133
(*ap.borrow_mut()).arg::<FnPtr<fn(i32, i32) -> i32>>();
3234
let mut result: i32 = ({ fn_.call(a, (*b.borrow())) });

‎tests/unit/out/refcount/va_arg_forward.rs‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use std::io::prelude::*;
66
use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
9-
pub fn inner_0(mut count: i32, ap: VaList) -> i32 {
10-
let ap: Value<VaList> = Rc::new(RefCell::new(ap));
9+
pub fn inner_0(mut count: i32, ap: Ptr<VaArg>) -> i32 {
10+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(ap));
1111
let mut total: i32 = 0;
1212
let mut i: i32 = 0;
1313
'loop_: while (((i < count) as i32) != 0) {
@@ -17,9 +17,10 @@ pub fn inner_0(mut count: i32, ap: VaList) -> i32 {
1717
return total;
1818
}
1919
pub fn outer_1(count: i32, __args: &[VaArg]) -> i32 {
20+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
2021
let count: Value<i32> = Rc::new(RefCell::new(count));
21-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
22-
(*ap.borrow_mut()) = VaList::new(__args);
22+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
23+
(*ap.borrow_mut()) = __args.as_pointer();
2324
let mut result: i32 = ({ inner_0((*count.borrow()), (*ap.borrow()).clone()) });
2425
return result;
2526
}

‎tests/unit/out/refcount/va_arg_mixed_int_ptr.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn mixed_args_0(count: i32, __args: &[VaArg]) -> i32 {
10+
let __args: Value<Box<[VaArg]>> = Rc::new(RefCell::new(__args.into()));
1011
let count: Value<i32> = Rc::new(RefCell::new(count));
11-
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
12-
(*ap.borrow_mut()) = VaList::new(__args);
12+
let ap: Value<Ptr<VaArg>> = Rc::new(RefCell::new(Ptr::<VaArg>::default()));
13+
(*ap.borrow_mut()) = __args.as_pointer();
1314
let mut total: i32 = 0;
1415
let mut i: i32 = 0;
1516
'loop_: while (((i < (*count.borrow())) as i32) != 0) {

0 commit comments

Comments
 (0)