-
-
Notifications
You must be signed in to change notification settings - Fork 265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix segmentation fault when compiling va_arg intrinsic #4336
base: master
Are you sure you want to change the base?
Conversation
Looks like this needs a little more work on aarch64 hosts? I'm not really able to debug that at the moment. |
From what I've seen, that intrinsic is basically useless, and we need to do it manually in druntime. Under examples, https://llvm.org/docs/LangRef.html#va-arg-instruction states:
A slice like |
Yep, LLVM doesn't implement the target C ABI (the lowering is done in Clang); consequently, the intrinsic is also useless, as it would be missing the requisite translation of types according to the respective ABI details. |
That is unfortunate. It would still be good for LDC to support emitting the intrinsic, even if LLVM doesn't handle it well. Either that or the LDC intrinsic for it should not exist, and shouldn't be listed on the wiki here: https://wiki.dlang.org/LDC-specific_language_changes#LDC_va_.2A_for_variadic_argument_handling_intrinsics. For my target platforms (riscv64-unknown-elf and aarch64-none-elf), the LLVM va_arg instruction appears to work, but maybe I should just use the D runtime implementation because LLVM va_arg is half-baked. |
Well years ago when I last looked at varargs stuff, the |
Ah, so the other 3 va_* intrinsics are intrinsic functions, but Lines 1571 to 1573 in 981c58e
Besides skipping the IR declaration of the D function, we should probably handle Lines 713 to 723 in 981c58e
|
This seemingly does the job: diff --git a/gen/toir.cpp b/gen/toir.cpp
index 6a2c00052e..421b7d0e1a 100644
--- a/gen/toir.cpp
+++ b/gen/toir.cpp
@@ -719,6 +719,12 @@ public:
if (fd->llvmInternal == LLVMinline_ir) {
return DtoInlineIRExpr(e->loc, fd, e->arguments, sretPointer);
}
+ if (fd->llvmInternal == LLVMva_arg) {
+ DValue *result = nullptr;
+ const auto success = DtoLowerMagicIntrinsic(p, fd, e, result);
+ assert(success);
+ return result;
+ }
}
}
Little test file: import core.stdc.stdarg : va_list;
pragma(LDC_va_arg) T va_arg(T)(ref va_list ap);
int foo(...) {
return va_arg!int(_argptr);
}
void main() {
assert(foo(123) == 123);
} Compiling with
|
Ah I see that is unfortunate for aarch64-none-elf. I'll just use the D runtime version I think. I can close this PR if you want to commit your fix separately. |
The following code currently causes a segmentation fault in LDC when compiled:
This PR fixes that.
Note: the following code still causes a segfault during compilation, but I think this is a bug in LLVM, not LDC.
I will report that separately to the LLVM project.
Also, it seems like the D runtime that LDC uses does not make use of the
va_arg
intrinsic, and instead uses custom code for each architecture (from DMD I assume). What is the reason for this? Using some custom implementation instead of relying on the LLVM intrinsic seems much more prone to bugs. Perhaps some followup work to this PR would be to convert D runtime over to using theva_arg
intrinsic for LDC instead of the (hacky?) one from DMD.