<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Hi Rel,<span><br>
</span></p>
<p><span>> 1. Am I doing something wrong in C++ test so that it
crashes?</span></p>
<p>I can't say for sure without seeing the struct's definition.<br>
<br>
Note though that, there are many cases in which the C and C++ ABIs
differ. At least for the moment, the FFM linker only supports
linking using the C ABI, so in order to reliably call C++, you
would have to define the C++ functions with C linkage (using
`extern "C"`).</p>
<p>> <span>Is it done in purpose or I am looking at a wrong
documentation and usage of <span>SegmentAllocator</span> in <span>invokeExact</span>
described somewhere else?</span></p>
<p><span>The documentation of invokeExact is very general, and
doesn't cover the FFM's use of method handles in particular. You
can find a description of the additional SegmentAllocator
parameter in the documentation of Linker::downcallHandle [1].
E.g. "</span>... if the function descriptor's return layout is a
group layout, the resulting downcall method handle accepts an
additional leading parameter of type SegmentAllocator, which is
used by the linker runtime to allocate the memory region
associated with the struct returned by the downcall method handle.
"</p>
<p>> 3. Any ideas on how rust-bindgen deals with <span>RVO</span>?</p>
<p>As far as I know, rust-bindgen only generations functions with C
linkage, so RVO is not in the picture.<br>
</p>
<p><span></span></p>
<p>Jorn</p>
<p>[1]:
<a class="moz-txt-link-freetext" href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/Linker.html#downcallHandle(java.lang.foreign.FunctionDescriptor,java.lang.foreign.Linker.Option...)">https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/Linker.html#downcallHandle(java.lang.foreign.FunctionDescriptor,java.lang.foreign.Linker.Option...)</a><br>
</p>
<div class="moz-cite-prefix">On 24/09/2023 20:10, Rel wrote:<br>
</div>
<blockquote type="cite" cite="mid:T0fMEeQsA-CkOmbwFCKU4_llTHmz9pDWM4Pvo7xK8xw2EBAyAPzK5-BbFISuYWyKN9zd6uWjJLLRzpdMMsuZKEkDmvydrmBG_K46LHv6svE=@proton.me">
<span>Hi all,</span>
<div><br>
</div>
<div><span>Currently my main focus is to support:</span></div>
<div><br>
</div>
<div><span>std::string helloWorld();</span></div>
<div><br>
</div>
<div><span>I managed to generate "some" layout for std::string but
I encountered problems of a different level :)</span></div>
<div><br>
</div>
<div><span>Let's take more simple examples where function will
return object and do it for C first:</span></div>
<div><br>
</div>
<div><span>struct B returnStruct(); // C</span></div>
<div><br>
</div>
<div><span>My test looks like:</span></div>
<div><br>
</div>
<div><span> var alloc =
SegmentAllocator.slicingAllocator(Arena.ofAuto().allocate(B.sizeof()));</span></div>
<div><span> assertEquals(10,
A.a$get(B.a$slice(Libcexperiments.returnStruct(alloc))));</span></div>
<div><br>
</div>
<div><span>It passes.</span></div>
<div><br>
</div>
<div><span>Now C++ test:</span></div>
<div><br>
</div>
<div><span>Point2d createPoint2d(); // C++</span></div>
<div><br>
</div>
<div><span>The way C++ returns objects (struct/class) is not very
similar to C. It highly depends on C++ RVO (<a target="_blank" rel="noreferrer nofollow noopener" href="https://sigcpp.github.io/2020/06/08/return-value-optimization" moz-do-not-send="true" class="moz-txt-link-freetext">https://sigcpp.github.io/2020/06/08/return-value-optimization</a>).
Currently I try to disable it by compiling libcppexperiments
with -fno-elide-constructors and call copy ctors which is
generated by the compiler</span></div>
<div><br>
</div>
<div><span>My test looks like:</span></div>
<div><br>
</div>
<div><span> var mem =
Arena.global().allocate(Point2d.sizeof());</span></div>
<div><span> printDump(mem.asByteBuffer());</span></div>
<div><span> var pointAlloc =
SegmentAllocator.slicingAllocator(mem);</span></div>
<div><span> var pointPtr2 =
Happy.createPoint2d(pointAlloc);</span></div>
<div><span> printDump(mem.asByteBuffer());</span></div>
<div><br>
</div>
<div><span>The result is:</span></div>
<div><br>
</div>
<div><span>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 </span></div>
<div><span>happy::Point::Point(this = 0x7fbc2c533f70)</span></div>
<div><span>happy::Point2d::Point2d(20, 22)</span></div>
<div><span>7fbc2c533f70</span></div>
<div><span>30 cd 04 30 bc 7f 00 00 14 00 00 00 16 00 00 00 </span></div>
<div><span>[x=20,y=22]</span></div>
<div><span>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 </span></div>
<div><span>happy::createPoint2d</span></div>
<div><span>happy::Point::Point(this = 0x7fbc33dbddd0)</span></div>
<div><span>happy::Point2d::Point2d(2, 3)</span></div>
<div><span>#</span></div>
<div><span># A fatal error has been detected by the Java Runtime
Environment:</span></div>
<div><span>#</span></div>
<div><span># SIGSEGV (0xb) at pc=0x00007fbc30049bf9, pid=2704200,
tid=2704208</span></div>
<div><span>#</span></div>
<div><span># JRE version: OpenJDK Runtime Environment (22.0+12)
(build 22-ea+12-877)</span></div>
<div><span># Java VM: OpenJDK 64-Bit Server VM (22-ea+12-877,
mixed mode, sharing, tiered, compressed oops, compressed class
ptrs, g1 gc, linux-amd64)</span></div>
<div><span># Problematic frame:</span></div>
<div><span># C [libcppexperiments.so+0x2bf9]
happy::Point::Point(happy::Point const&)+0x1f</span></div>
<div><br>
</div>
<div><span>I have two questions:</span></div>
<div><br>
</div>
<div><span>1.</span></div>
<div><span>Am I doing something wrong in C++ test so that it
crashes?</span></div>
<div><br>
</div>
<div><span>2.</span></div>
<div><span>It seems that C++ tries to copy data to memory which
suppose to be provided by pointAlloc</span></div>
<div><br>
</div>
<div><span>When jextract (prod version) generates code for such
example in C, it expects users to define SegmentAllocator and
it passes it to MethodHandle::invokeExact. The documentation
of invokeExact is vague and it says that:</span></div>
<div><br>
</div>
<div><span>> args - the signature-polymorphic parameter list,
statically represented using varargs</span></div>
<div><br>
</div>
<div><span>and does not cover usecase that args may contain
SegmentAllocator (I guess it is to allocate memory where
returned object will we saved?). Is it done in purpose or I am
looking at a wrong documentation and usage of <span>SegmentAllocator</span>
in <span>invokeExact</span> described somewhere else?</span></div>
<div style="font-family: Arial, sans-serif; font-size: 14px;
color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"><br>
</div>
<div style="font-family: Arial, sans-serif; font-size: 14px;
color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">3.</div>
<div style="font-family: Arial, sans-serif; font-size: 14px;
color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">Any
ideas on how rust-bindgen deals with <span>RVO</span>?</div>
<div style="font-family: Arial, sans-serif; font-size: 14px;
color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"><br>
</div>
<div style="font-family: Arial, sans-serif; font-size: 14px;
color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">Regards,<br>
</div>
<span></span>
<div class="protonmail_quote"> ------- Original Message -------<br>
On Wednesday, September 6th, 2023 at 12:34 AM, Rel
<a class="moz-txt-link-rfc2396E" href="mailto:enatai@proton.me"><enatai@proton.me></a> wrote:<br>
<br>
<blockquote class="protonmail_quote" type="cite">
<div style="font-family: Arial, sans-serif; font-size: 14px;"><span>Short
updates from me.</span>
<div><br>
</div>
<div><span>I continue working on generating layout for
std::string and found that it is failing on cxx branch:</span></div>
<div><br>
</div>
<div><span>Scoped: TOPLEVEL <toplevel></span></div>
<div><span> Scoped: STRUCT __mbstate_t layout =
[i32(__count)[i32(__wch)|[4:b8](__wchb)](__value)](__mbstate_t)</span></div>
<div><span> Attr: LINK -> []</span></div>
<div><span> Variable: FIELD __count type = Int(layout
= i32)</span></div>
<div><span> Variable: FIELD __value type =
Declared([i32(__wch)|[4:b8](__wchb)](union (unnamed at
enum.h:28:3)))</span></div>
<div><br>
</div>
<div><span>java.lang.IllegalArgumentException: Invalid
member name: union (unnamed at enum.h:28:3)</span></div>
<div><span> at
java.base/java.lang.constant.ConstantUtils.validateMemberName(ConstantUtils.java:152)</span></div>
<div><span> at
java.base/java.lang.constant.ClassDesc.of(ClassDesc.java:129)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.ClassSourceBuilder">org.openjdk.jextract@21/org.openjdk.jextract.impl.ClassSourceBuilder</a>.<init>(ClassSourceBuilder.java:70)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.StructBuilder">org.openjdk.jextract@21/org.openjdk.jextract.impl.StructBuilder</a>.<init>(StructBuilder.java:67)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.StructBuilder">org.openjdk.jextract@21/org.openjdk.jextract.impl.StructBuilder</a>.<init>(StructBuilder.java:62)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.StructBuilder.addStruct">org.openjdk.jextract@21/org.openjdk.jextract.impl.StructBuilder.addStruct</a>(StructBuilder.java:136)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitScoped">org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitScoped</a>(OutputFactory.java:187)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitScoped">org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitScoped</a>(OutputFactory.java:54)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.DeclarationImpl$ScopedImpl.accept">org.openjdk.jextract@21/org.openjdk.jextract.impl.DeclarationImpl$ScopedImpl.accept</a>(DeclarationImpl.java:333)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitVariable">org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitVariable</a>(OutputFactory.java:354)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitVariable">org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.visitVariable</a>(OutputFactory.java:54)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.DeclarationImpl$VariableImpl.accept">org.openjdk.jextract@21/org.openjdk.jextract.impl.DeclarationImpl$VariableImpl.accept</a>(DeclarationImpl.java:172)</span></div>
<div><span> at
<a class="moz-txt-link-abbreviated" href="mailto:org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.lambda$visitScoped$0">org.openjdk.jextract@21/org.openjdk.jextract.impl.OutputFactory.lambda$visitScoped$0</a>(OutputFactory.java:201)</span></div>
<div><br>
</div>
<div><span>But same worked with latest changes in panama
branch.</span></div>
<div><br>
</div>
<div><span>In order to update cxx branch to panama branch I
decided to use rebase
instead of merge (I see Maurizio was merging them
instead). The reason
why I did rebase is that way our cpp changes will be
always on top of
whatever changes were done in panama branch (and not
spread across the
branch) so it will be easy to track them.</span></div>
<div><br>
</div>
<div><span>Initially we had following branch:</span></div>
<div><span>cxx - Maurizio initial cpp support</span></div>
<div><br>
</div>
<div><span>Now I added cxx2 branch which is rebase on latest
panama branch with Maurizio changes.<br>
</span></div>
<div><br>
</div>
<div><span>Now, if you remember previously we did mangle
only for member functions, and
for ordinary functions we had define wrapper manually
like:</span></div>
<div><br>
</div>
<div><span><a target="_blank" rel="noreferrer nofollow
noopener" href="https://github.com/enatai/panamaexperiments/blob/ec76f9c2d25734a8c9f93f6b4200161b353c81f0/cppexperiments/src/main/java/libcppexperiments/CalcDistance.java" moz-do-not-send="true" class="moz-txt-link-freetext">https://github.com/enatai/panamaexperiments/blob/ec76f9c2d25734a8c9f93f6b4200161b353c81f0/cppexperiments/src/main/java/libcppexperiments/CalcDistance.java</a></span></div>
<div><br>
</div>
<div><span>I fixed it so jextract mangles, in case of C++,
non member functions too:</span></div>
<div><br>
</div>
<div><span><a target="_blank" rel="noreferrer nofollow
noopener" href="https://github.com/enatai/jextractcpp/commit/f1f64e31702b06aa9325546013758ce912f36363" moz-do-not-send="true" class="moz-txt-link-freetext">https://github.com/enatai/jextractcpp/commit/f1f64e31702b06aa9325546013758ce912f36363</a></span></div>
<span></span>
<div><br>
</div>
<div><span>I plan to continue to do my changes in cxx2
branch and keep rebasing it to panama branch once in a
while</span></div>
<br>
</div>
</blockquote>
<br>
</div>
</blockquote>
</body>
</html>