[PATCH] D138511: [CodeGen][AArch64] Fix AArch64ABIInfo::EmitAAPCSVAArg crash with empty record type in variadic arg
Yurong via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 29 10:12:12 PST 2022
yronglin added a comment.
In D138511#3954143 <https://reviews.llvm.org/D138511#3954143>, @efriedma wrote:
> It looks like AArch64ABIInfo::classifyArgumentType does a slightly more complicated check for "empty"; does that matter here?
Thanks for your comments @efriedma. Good catch! Current patch has a issue in this case(C++ mode):
clang -Xclang -no-opaque-pointers -target aarch64-linux-gnu -emit-llvm -S ./va_arg.cpp
typedef __builtin_va_list va_list;
#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_end(ap) __builtin_va_end(ap)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
va_list the_list;
typedef struct {} empty;
empty empty_record_test(void) {
return va_arg(the_list, empty);
}
When use `isEmptyRecord` directly to check empty record, the generated IR is:
define dso_local void @_Z17empty_record_testv() #0 {
entry:
%0 = load i8*, i8** getelementptr inbounds (%"struct.std::__va_list", %"struct.std::__va_list"* @the_list, i32 0, i32 0), align 8
%1 = bitcast i8* %0 to %struct.empty*
ret void
}
When use `AArch64ABIInfo::classifyArgumentType(...).isIgnore()` to check empty record, the generated IR is:
define dso_local void @_Z17empty_record_testv() #0 {
entry:
%gr_offs = load i32, i32* getelementptr inbounds (%"struct.std::__va_list", %"struct.std::__va_list"* @the_list, i32 0, i32 3), align 8
%0 = icmp sge i32 %gr_offs, 0
br i1 %0, label %vaarg.on_stack, label %vaarg.maybe_reg
vaarg.maybe_reg: ; preds = %entry
%new_reg_offs = add i32 %gr_offs, 8
store i32 %new_reg_offs, i32* getelementptr inbounds (%"struct.std::__va_list", %"struct.std::__va_list"* @the_list, i32 0, i32 3), align 8
%inreg = icmp sle i32 %new_reg_offs, 0
br i1 %inreg, label %vaarg.in_reg, label %vaarg.on_stack
vaarg.in_reg: ; preds = %vaarg.maybe_reg
%reg_top = load i8*, i8** getelementptr inbounds (%"struct.std::__va_list", %"struct.std::__va_list"* @the_list, i32 0, i32 1), align 8
%1 = getelementptr inbounds i8, i8* %reg_top, i32 %gr_offs
%2 = bitcast i8* %1 to %struct.empty2*
br label %vaarg.end
vaarg.on_stack: ; preds = %vaarg.maybe_reg, %entry
%stack = load i8*, i8** getelementptr inbounds (%"struct.std::__va_list", %"struct.std::__va_list"* @the_list, i32 0, i32 0), align 8
%new_stack = getelementptr inbounds i8, i8* %stack, i64 8
store i8* %new_stack, i8** getelementptr inbounds (%"struct.std::__va_list", %"struct.std::__va_list"* @the_list, i32 0, i32 0), align 8
%3 = bitcast i8* %stack to %struct.empty2*
br label %vaarg.end
vaarg.end: ; preds = %vaarg.on_stack, %vaarg.in_reg
%vaargs.addr = phi %struct.empty2* [ %2, %vaarg.in_reg ], [ %3, %vaarg.on_stack ]
ret void
}
As far as I know, according to the comments of the `AArch64ABIInfo::classifyArgumentType(...)`, "Empty records are always ignored on Darwin, but actually passed in C++ mode elsewhere for GNU compatibility." and "GNU C mode. The only argument that gets ignored is an empty one with size 0.", I think we should ignore arg only if DarwinPCS ABI and empty record in C mode. What do you all think about?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D138511/new/
https://reviews.llvm.org/D138511
More information about the cfe-commits
mailing list