Refactor ConvertGenericCallExpr#145
Conversation
| using Kind = CallArg::Kind; | ||
|
|
||
| unsigned arg_begin = 0; // skip count for operator()'s implicit object arg | ||
| CallInfo info{}; |
| } | ||
| } | ||
|
|
||
| void Converter::EmitCall(CallInfo info) { |
There was a problem hiding this comment.
I changed to CalInfo&& info
| Materialized, | ||
| }; | ||
|
|
||
| clang::Expr *expr; |
There was a problem hiding this comment.
usually these are sorted by size (larger to shorter) to reduce struct size.
| std::optional<TempMaterializationCtx> ConvertCallExpr(clang::CallExpr *expr); | ||
|
|
||
| struct CallArg { | ||
| enum class Kind { |
| case Kind::Hoisted: | ||
| StrCat("let", | ||
| std::format("_{}: {}", ca.param_name, ToString(ca.param_type)), | ||
| "="); |
There was a problem hiding this comment.
Replaced with std::format("let {}: {} =")
| bool is_variadic; | ||
| bool is_fn_ptr_call; | ||
| std::vector<CallArg> args; | ||
| std::vector<clang::Expr *> variadic_args; |
There was a problem hiding this comment.
there's only up to one variadic arg. this can be a simple pointer initialized to null
There was a problem hiding this comment.
No, for example in the following code:
void foo(int a, ...);
foo(1, 2, 3);=>
args = 1,
variadic_args = 2, 3
And the Rust code is:
fn foo(a: i32, args: &[VaArg])
foo(1, &[2.into(), 3.into()])| std::string param_name; | ||
| std::string ref_temp_name; | ||
| clang::QualType param_type; | ||
| clang::Expr *expr; |
There was a problem hiding this comment.
switch param_type and expr
There was a problem hiding this comment.
The size of both param_type and expr is 8, I inspected using -fdump-record-layouts. Is there other reason for switching?
Dump of -Xclang -fdump-record-layouts
*** Dumping AST Record Layout
0 | struct cpp2rust::Converter::CallArg
0 | class std::basic_string<char> param_name
0 | struct std::basic_string<char>::_Alloc_hider _M_dataplus
0 | class std::allocator<char> (base) (empty)
0 | class std::__new_allocator<char> (base) (empty)
0 | pointer _M_p
8 | size_type _M_string_length
16 | union std::basic_string<char>::(anonymous at /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/basic_string.h:204:7)
16 | char[16] _M_local_buf
16 | size_type _M_allocated_capacity
32 | class std::basic_string<char> ref_temp_name
32 | struct std::basic_string<char>::_Alloc_hider _M_dataplus
32 | class std::allocator<char> (base) (empty)
32 | class std::__new_allocator<char> (base) (empty)
32 | pointer _M_p
40 | size_type _M_string_length
48 | union std::basic_string<char>::(anonymous at /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/basic_string.h:204:7)
48 | char[16] _M_local_buf
48 | size_type _M_allocated_capacity
64 | class clang::QualType param_type
64 | class llvm::PointerIntPair<class llvm::PointerUnion<const class clang::Type *, const class clang::ExtQuals *>, 3> Value
64 | struct llvm::detail::PunnedPointer<class llvm::PointerUnion<const class clang::Type *, const class clang::ExtQuals *> > Value
64 | unsigned char[8] Data
72 | clang::Expr * expr
80 | _Bool has_default
81 | Kind kind
| [sizeof=88, dsize=82, align=8,
| nvsize=82, nvalign=8]
|
|
||
| struct CallInfo { | ||
| clang::Expr *callee; | ||
| bool is_variadic; |
There was a problem hiding this comment.
is_variadic isn't equal to !variadic_args.empty()?
There was a problem hiding this comment.
No, a variadic function call be called with 0 variadic arguments, in which case we need to emit an empty &[VaArgs] like this: foo(0, &[])
| } | ||
| } | ||
|
|
||
| void Converter::EmitCall(CallInfo &&info) { |
There was a problem hiding this comment.
const CallInfo &
The function doesn't consume or take ownership
There was a problem hiding this comment.
It can't be const CallInfo & because EmitHoistedArgs which is called inside EmitCall takes a CallInfo&. But EmitCall can be CallInfo&
ConvertGenericCallExpr is a messy function and it became difficult to add new functoinality on top of it. So I decided to refactor it into:
EmitCall(CollectCallInfo(expr)).In the near future I plan to add 3 new features on top of it:
In the new version of ConvertGenericCallExpr, CollectCallInfo is responsible for returning the call information:
And EmitCall is responsible for emitting the hoisted arguments, the callee and the argument list using a CallInfo.
This model makes the addition of new strategies, for example
Don't hoist arguments that are integer literals, they don't alias with any other argument, easier because only the CallInfo fields have to be modified.