Closed kencu closed 1 year ago
mentioned in issue llvm/llvm-bugzilla-archive#39692
although the tests above appeared to work correctly, I should point out that on running the test-suite, there were two fails in the va_args section:
test-suite :: SingleSource/UnitTests/2003-05-07-VarArgs.test
test-suite :: SingleSource/UnitTests/2003-08-11-VaListArg.test
==================
FAIL: test-suite :: SingleSource/UnitTests/2003-08-11-VaListArg.test (411 of 500) **** TEST 'test-suite :: SingleSource/UnitTests/2003-08-11-VaListArg.test' FAILED ****
/Users/macportsdev/test-suite/RunSafely.sh -t /Users/macportsdev/test-suite-build/tools/timeit 7200 /dev/null /Users/macportsdev/test-suite-build/SingleSource/UnitTests/Output/2003-08-11-VaListArg.test.out /Users/macportsdev/test-suite-build/SingleSource/UnitTests/2003-08-11-VaListArg /Users/macportsdev/test-suite-build/tools/fpcmp /Users/macportsdev/test-suite-build/SingleSource/UnitTests/Output/2003-08-11-VaListArg.test.out /Users/macportsdev/test-suite/SingleSource/UnitTests/2003-08-11-VaListArg.reference_output
/Users/macportsdev/test-suite-build/tools/fpcmp: files differ without tolerance allowance
$ cat /Users/macportsdev/test-suite-build/SingleSource/UnitTests/Output/2003-05-07-VarArgs.test.out string abc string def int -123 char a int 123 int 6 int 7 int 8 int 9 string 10 args done! double 1.000000 double 2.000000 int 32764 long long 12345677823423 DWord { 18, a } QuadWord { 0, 0.000000 } LargeS { 0, 0.000000, 0x1, 0 } exit 0 LeopardG5:~ macportsdev$ cat /Users/macportsdev/test-suite/SingleSource/UnitTests/2003-05-07-VarArgs.reference_output string abc string def int -123 char a int 123 int 6 int 7 int 8 int 9 string 10 args done! double 1.000000 double 2.000000 int 32764 long long 12345677823423 DWord { 18, a } QuadWord { 19, 20.000000 } LargeS { 21, 22.000000, 0x1, 23 } exit 0
============================
FAIL: test-suite :: SingleSource/UnitTests/2003-05-07-VarArgs.test (399 of 500) **** TEST 'test-suite :: SingleSource/UnitTests/2003-05-07-VarArgs.test' FAILED ****
/Users/macportsdev/test-suite/RunSafely.sh -t /Users/macportsdev/test-suite-build/tools/timeit 7200 /dev/null /Users/macportsdev/test-suite-build/SingleSource/UnitTests/Output/2003-05-07-VarArgs.test.out /Users/macportsdev/test-suite-build/SingleSource/UnitTests/2003-05-07-VarArgs /Users/macportsdev/test-suite-build/tools/fpcmp /Users/macportsdev/test-suite-build/SingleSource/UnitTests/Output/2003-05-07-VarArgs.test.out /Users/macportsdev/test-suite/SingleSource/UnitTests/2003-05-07-VarArgs.reference_output
/Users/macportsdev/test-suite-build/tools/fpcmp: files differ without tolerance allowance
$ cat /Users/macportsdev/test-suite-build/SingleSource/UnitTests/Output/2003-05-07-VarArgs.test.out string abc string def int -123 char a int 123 int 6 int 7 int 8 int 9 string 10 args done! double 1.000000 double 2.000000 int 32764 long long 12345677823423 DWord { 18, a } QuadWord { 0, 0.000000 } LargeS { 0, 0.000000, 0x1, 0 } exit 0
$ cat /Users/macportsdev/test-suite/SingleSource/UnitTests/2003-05-07-VarArgs.reference_output string abc string def int -123 char a int 123 int 6 int 7 int 8 int 9 string 10 args done! double 1.000000 double 2.000000 int 32764 long long 12345677823423 DWord { 18, a } QuadWord { 19, 20.000000 } LargeS { 21, 22.000000, 0x1, 23 } exit 0
==============
Works perfectly!! Thanks very much for you time and interest. Ken
$ clang -arch ppc -o vatest2.ppc vatest2.cpp $ ./vatest2.ppc number of values: 3 value 1 is: 3 value 2 is: 4 value 3 is: 5 number of values: 7 value 1 is: 3 value 2 is: 4 value 3 is: 5 value 4 is: 4 value 5 is: 3 value 6 is: 2 value 7 is: 1
$ clang -arch ppc -o vatest3.ppc vatest3.cpp $ ./vatest3.ppc number of values: 3 value 1 is: 3.100000 value 2 is: 4.200000 value 3 is: 5.300000 number of values: 3 value 1 is: 3.100000 value 2 is: 4.200000 value 3 is: 5.300000
$ clang -arch ppc -o vatest2.ppc vatest2.cpp $ ./vatest2.ppc number of values: 3 value 1 is: 3 value 2 is: 4 value 3 is: 5 number of values: 7 value 1 is: 3 value 2 is: 4 value 3 is: 5 value 4 is: 4 value 5 is: 3 value 6 is: 2 value 7 is: 1
$ clang -arch ppc -o vatest4.ppc vatest4.cpp $ ./vatest4.ppc value is: 3.100000
Thanks, this was helpful.
I updated the patch at: https://reviews.llvm.org/D33499. I hope this will solve the problems.
One extra build that might be useful. This a build of vatest4.cpp using apple-gcc42, which frontended gcc 4.2 and backended llvm (version?). This produces properly working code as well.
$ gcc -v Using built-in specs. Target: powerpc-apple-darwin9 Configured with: /var/tmp/gcc_42/gcc_42-5577~1/src/configure --disable-checking --prefix=/usr --mandir=/usr/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin9 --with-gxx-include-dir=/usr/include/c++/4.0.0 --program-prefix= --host=powerpc-apple-darwin9 --target=powerpc-apple-darwin9 Thread model: posix gcc version 4.2.1 (Apple Inc. build 5577)
$ gcc -arch ppc -S vatest4.cpp
$ cat vatest4.s .section TEXT,text,regular,pure_instructions .section TEXT,picsymbolstub1,symbol_stubs,pure_instructions,32 .machine ppc7400 .cstring .align 2 LC0: .ascii "value is: %f\12\0" .text .align 2 .globl Z7printmeiz Z7printmeiz: LFB3: mflr r0 LCFI0: stmw r30,-8(r1) LCFI1: stw r0,8(r1) LCFI2: stwu r1,-112(r1) LCFI3: mr r30,r1 LCFI4: bcl 20,31,"L00000000001$pb" "L00000000001$pb": mflr r31 stw r4,140(r30) stw r5,144(r30) stw r6,148(r30) stw r7,152(r30) stw r8,156(r30) stw r9,160(r30) stw r10,164(r30) stw r3,136(r30) addi r0,r30,140 stw r0,56(r30) lwz r2,56(r30) addi r0,r2,8 stw r0,56(r30) lfd f0,0(r2) stfd f0,80(r30) lwz r2,80(r30) lwz r3,84(r30) mr r10,r3 mr r9,r2 stw r2,80(r30) stw r3,84(r30) lfd f13,80(r30) fmr f0,f13 addis r2,r31,ha16(LC0-"L00000000001$pb") la r3,lo16(LC0-"L00000000001$pb")(r2) mr r4,r9 mr r5,r10 fmr f1,f0 bl _printf$LDBL128 lwz r1,0(r1) lwz r0,8(r1) mtlr r0 lmw r30,-8(r1) blr LFE3: .align 2 .globl _main _main: LFB4: mflr r0 LCFI5: stmw r30,-8(r1) LCFI6: stw r0,8(r1) LCFI7: stwu r1,-96(r1) LCFI8: mr r30,r1 LCFI9: bcl 20,31,"L00000000002$pb" "L00000000002$pb": mflr r31 addis r2,r31,ha16(LC1-"L00000000002$pb") la r2,lo16(LC1-"L00000000002$pb")(r2) lfd f0,0(r2) stfd f0,64(r30) lwz r2,64(r30) lwz r3,68(r30) mr r10,r3 mr r9,r2 stw r2,64(r30) stw r3,68(r30) lfd f13,64(r30) fmr f0,f13 li r3,1 mr r4,r9 mr r5,r10 fmr f1,f0 bl Z7printmeiz li r0,0 mr r3,r0 lwz r1,0(r1) lwz r0,8(r1) mtlr r0 lmw r30,-8(r1) blr LFE4: .literal8 .align 3 LC1: .long 1074318540 .long -858993459 .section TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support EH_frame1: .set L$set$0,LECIE1-LSCIE1 .long L$set$0 LSCIE1: .long 0x0 .byte 0x1 .ascii "zPR\0" .byte 0x1 .byte 0x7c .byte 0x41 .byte 0x6 .byte 0x9b .long L_gxx_personality_v0$non_lazy_ptr-. .byte 0x10 .byte 0xc .byte 0x1 .byte 0x0 .align 2 LECIE1: .globl Z7printmeiz.eh Z7printmeiz.eh: LSFDE1: .set L$set$1,LEFDE1-LASFDE1 .long L$set$1 LASFDE1: .long LASFDE1-EH_frame1 .long LFB3-. .set L$set$2,LFE3-LFB3 .long L$set$2 .byte 0x0 .byte 0x4 .set L$set$3,LCFI3-LFB3 .long L$set$3 .byte 0xe .byte 0x70 .byte 0x9f .byte 0x1 .byte 0x9e .byte 0x2 .byte 0x11 .byte 0x41 .byte 0x7e .byte 0x4 .set L$set$4,LCFI4-LCFI3 .long L$set$4 .byte 0xd .byte 0x1e .align 2 LEFDE1: .globl _main.eh _main.eh: LSFDE3: .set L$set$5,LEFDE3-LASFDE3 .long L$set$5 LASFDE3: .long LASFDE3-EH_frame1 .long LFB4-. .set L$set$6,LFE4-LFB4 .long L$set$6 .byte 0x0 .byte 0x4 .set L$set$7,LCFI8-LFB4 .long L$set$7 .byte 0xe .byte 0x60 .byte 0x9f .byte 0x1 .byte 0x9e .byte 0x2 .byte 0x11 .byte 0x41 .byte 0x7e .byte 0x4 .set L$set$8,LCFI9-LCFI8 .long L$set$8 .byte 0xd .byte 0x1e .align 2 LEFDE3: .non_lazy_symbolpointer Lgxx_personality_v0$non_lazy_ptr: .indirect_symbol ___gxx_personality_v0 .long 0 .constructor .destructor .align 1 .subsections_via_symbols
Here it is. I simplified the test case to hopefully reduce cruft. I'll also post up vatest3.s as an attachment as you requested that. - K
$ cat vatest4.cpp
void printme ( int num, ... )
{
va_list arguments;
va_start ( arguments, num );
printf( "value is: %f\n", va_arg ( arguments, double ) );
va_end ( arguments );
}
int main() { printme(1, 3.1); }
============ outputs:
$ ./vatest4.ppc value is: -92559677937162871625617509558218198585493561317703376340779008.000000
============== $ clang -arch ppc -S vatest4.cpp $ cat vatest4.s .section TEXT,text,regular,pure_instructions .macosx_version_min 10, 5 .machine ppc .section TEXT,textcoal_nt,coalesced,pure_instructions .section TEXT,picsymbolstub1,symbol_stubs,pure_instructions,32 .section TEXT,text,regular,pure_instructions .globl Z7printmeiz .align 4 Z7printmeiz: ; @_Z7printmeiz .cfi_startproc ; BB#0: mflr r0 stw r31, -4(r1) stw r0, 8(r1) stwu r1, -80(r1) Ltmp0: .cfi_def_cfa_offset 80 Ltmp1: .cfi_offset r31, -4 Ltmp2: .cfi_offset lr, 8 mr r31, r1 Ltmp3: .cfi_def_cfaregister r31 bl L0$pb L0$pb: mflr r2 addi r11, r31, 115 stw r10, 132(r31) stw r9, 128(r31) stw r8, 124(r31) stw r7, 120(r31) stw r6, 116(r31) stw r5, 112(r31) stw r4, 108(r31) rlwinm r4, r11, 0, 0, 28 addi r5, r31, 108 stw r3, 72(r31) addi r6, r4, 8 stw r5, 68(r31) stw r6, 68(r31) lfd f0, 0(r4) stfd f0, 28(r1) addis r2, r2, ha16(L.str-L0$pb) lwz r5, 32(r1) lwz r4, 28(r1) la r2, lo16(L_.str-L0$pb)(r2) stw r3, 64(r31) ; 4-byte Folded Spill mr r3, r2 fmr f1, f0 bl _printf$LDBL128 ; lwz r2, 64(r31) ; 4-byte Folded Reload ; addi r1, r1, 80 lwz r0, 8(r1) lwz r31, -4(r1) mtlr r0 blr .cfi_endproc
.section __TEXT,__literal8,8byte_literals
.align 3
LCPI1_0: .long 1074318540 ; double 3.1000000000000001 .long 3435973837 .section TEXT,text,regular,pure_instructions .globl _main .align 4 _main: ; @main .cfi_startproc ; BB#0: mflr r0 stw r31, -4(r1) stw r0, 8(r1) stwu r1, -64(r1) Ltmp4: .cfi_def_cfa_offset 64 Ltmp5: .cfi_offset r31, -4 Ltmp6: .cfi_offset lr, 8 mr r31, r1 Ltmp7: .cfi_def_cfa_register r31 bl L1$pb L1$pb: mflr r2 lis r3, -13108 lis r4, 16392 ori r3, r3, 52429 ori r4, r4, 52428 addis r2, r2, ha16(LCPI1_0-L1$pb) stw r3, 32(r1) stw r4, 28(r1) lfd f1, lo16(LCPI1_0-L1$pb)(r2) lwz r5, 32(r1) lwz r4, 28(r1) li r3, 1 bl __Z7printmeiz li r3, 0 addi r1, r1, 64 lwz r0, 8(r1) lwz r31, -4(r1) mtlr r0 blr .cfi_endproc
.subsections_via_symbols .section TEXT,cstring,cstringliterals L.str: ; @.str .asciz "value is: %f\n"
The values picked up by printme are shifted by 4 bytes, so what gets printed is half of one double and half of the next one. It's as if there was a disagreement between the caller and the callee on the alignment of doubles. I'll have to go over the MacOS ABI to see which side is wrong, but out of curiosity, do you have a working C compiler on that system? If so, could you compile vatest3.cpp with -S and post the .s file? If not, that's ok, it's not critical.
va_args as ints seem to work, but as doubles do not.
I tested the va_args on 10.5 PPC with clang-3.8, using the patch I backported from Krzysztof's clang-4.0 patch (that patch is attached, in case you'd like to have a look at how I did it to make sure it's correct.
$ cat vatest2.cpp
void printme ( int num, ... )
{
va_list arguments;
int temp;
printf( "number of values: %d\n", num );
va_start ( arguments, num );
for ( int x = 0; x < num; x++ )
{
temp = va_arg ( arguments, int );
printf( "value %d is: %d\n", x+1, temp );
}
va_end ( arguments );
}
int main() { printme(3, 3, 4, 5); }
$ clang -arch ppc -o vatest2.ppc vatest2.cpp $ clang -arch i386 -o vatest2.i386 vatest2.cpp
OUTPUTS:
$ ./vatest2.i386 number of values: 3 value 1 is: 3 value 2 is: 4 value 3 is: 5
$ ./vatest2.ppc number of values: 3 value 1 is: 3 value 2 is: 4 value 3 is: 5
======================================
$ cat vatest3.cpp
void printme ( int num, ... )
{
va_list arguments;
double temp;
printf( "number of values: %d\n", num );
va_start ( arguments, num );
for ( int x = 0; x < num; x++ )
{
temp = va_arg ( arguments, double );
printf( "value %d is: %f\n", x+1, temp );
}
va_end ( arguments );
}
int main() { double a = 3.1; double b = 4.2; double c = 5.3;
printme(3, 3.1, 4.2, 5.3);
printme(3, a, b, c);
}
$ clang -arch i386 -o vatest3.i386 vatest3.cpp $ clang -arch ppc -o vatest3.ppc vatest3.cpp
$ ./vatest3.i386 number of values: 3 value 1 is: 3.100000 value 2 is: 4.200000 value 3 is: 5.300000 number of values: 3 value 1 is: 3.100000 value 2 is: 4.200000 value 3 is: 5.300000
$ ./vatest3.ppc number of values: 3 value 1 is: -92559653429824871689296838102125733553793312096835823269314560.000000 value 2 is: -92559653433117349428664821184862423824709207841093362739314688.000000 value 3 is: 0.000000 number of values: 3 value 1 is: -92559653429824871689296838102125733553793312096835823269314560.000000 value 2 is: -92559653433117349428664821184862423824709207841093362739314688.000000 value 3 is: 0.000000
===================================================================
Appreciate your help. Anything more I can do to help? Be happy to allow access to this machine if that is of value to you.
I backported this into clang-3.8 (the last version I can build on ppc at present) and it seems to work, at least initially. It doesn't segfault, at least, and it outputs assembly that looks - well - like assembly. I'll put the clang-3.8 patch up here for safekeeping, in case anyone else is interested.
$ cat pr.s .section TEXT,text,regular,pure_instructions .machine ppc .section TEXT,textcoal_nt,coalesced,pure_instructions .section TEXT,picsymbolstub1,symbol_stubs,pure_instructions,32 .section TEXT,text,regular,pure_instructions .globl Z1bv .align 4 Z1bv: lwz r2, -4(r1) addi r2, r2, 4 stw r2, -4(r1) blr
.subsections_via_symbols
I assume there is something in the test suite to put this code through it's paces and see if it is solid. Your message that it is a framework only is noted.
This may actually be the whole thing. From my reading of the MacOS documentation that I was able to find it seems like the variable argument list is simply passed as a pointer to the beginning of the parameter area. In such case, it should work fine as-is.
In any case, if you find any problems with it let me know and I'll try to fix them.
Thank you. I'll backport this into clang-3.8 and build it. (Clang 3.8 is the last version that I can presently build on 10.5 PPC, using gcc6 to build it. Newer versions error out.)
I assume there is something in the test suite to put this code through it's paces and see if it is solid. Your message that it is a framework only is noted.
Aside:
There must be thousands of Mac PPC machines still working - I have 8 of them - and although they can build a lot of software with gcc, there are many applications that have more advanced ObjC than gcc6 can handle. Clang-3.8 could keep these machines useful for a long time.
I'm also trying to see if I can build the MacPorts infrastructure as ppc64, and perhaps have better luck building ppc64 with clang that way, as the ppc64 output seems better fleshed out. Thank you for your time.
I added a really basic implementation of PPC32/Darwin ABI here: https://reviews.llvm.org/D33499.
All it does it that it uses the default handling of va_arg (based on void*).
It gets rid of the crash, but I don't know how far it is from the proper implementation. I cannot test it since I don't have PPC hardware anymore, let alone anything running MacOS.
I see. I notice there is an implementation of this char pointer based builtin_va_list handling in the rs6000 section of gcc4.2 (at least) and later.
This level of debugging is currently well over my head, but a question:
Is PPC32_SVR4_ABIInfo::EmitVAArg the proper call for PPC32 Darwin to be calling? I was under the impression SVR4 was more towards ELF unix.
I also saw a DefaultABIInfo::EmitVAArg mentioned as a replacement for above.
That is basically what Comment 7 is about:
Darwin support does:
BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; }
where the other PPC32 contexts do:
BuiltinVaListKind getBuiltinVaListKind() const override { // This is the ELF definition, and is overridden by the Darwin sub-target return TargetInfo::PowerABIBuiltinVaList; }
but overall the code does not support/handle Dawrin's
TargetInfo::CharPtrBuiltinVaList
It calls assuming the the
TargetInfo::PowerABIBuiltinVaList
context.
This level of debugging is currently well over my head, but a question:
Is PPC32_SVR4_ABIInfo::EmitVAArg the proper call for PPC32 Darwin to be calling? I was under the impression SVR4 was more towards ELF unix.
I also saw a DefaultABIInfo::EmitVAArg mentioned as a replacement for above.
I'm not familiar with the internals of the clang/llvm code. But looking around some I find some preliminary information (not necessarily looking at or testing with the same vintage llvm source code that you used):
The assert found a nullptr and rejected it. I worked backwards from that to how the nullptr was generated.
Summary of the later more full trace of the failure:
The nullptr was from finding CT->isPointerTy() true in getIndexedTypeInternal and that traces back to Darwin not being like other PPC32 cases for __builtin_va_list :
class DarwinPPC32TargetInfo : public DarwinTargetInfo
So I conclude some code structure is presuming that such a pointer based __builtin_va_list would not happen but it does.
Here is how I traced to the above and what I found in detail along the way. . .
The code that produced the nullptr used getIndexedType for a Value* based IdxList:
/// Returns the type of the element that would be loaded with /// a load instruction with the specified parameters. /// /// Null is returned if the indices are invalid for the specified /// pointer type. /// static Type getIndexedType(Type Ty, ArrayRef<Value *> IdxList);
Which makes it look like the IdxList generation involved was messed up.
CreateConstInBoundsGEP2_32 was given two 0 indexes and makes and uses:
Value *Idxs[] = {
ConstantInt::get(Type::getInt32Ty(Context), Idx0),
ConstantInt::get(Type::getInt32Ty(Context), Idx1)
};
The actual nullptr was produced by:
template
// If there is at least one index, the top level type must be sized, otherwise // it cannot be 'stepped over'. if (!Agg->isSized()) return nullptr;
unsigned CurIdx = 1;
for (; CurIdx != IdxList.size(); ++CurIdx) {
CompositeType *CT = dyn_cast
Stepping with the debugger (in a build not having full debug information available) it looks to me like
CT->isPointerTy()
was true, resulting in a nullptr return value that eventually is tested and asserts.
That means that in
Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset, const llvm::Twine &Name = "") { return Address(CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), Addr.getAlignment().alignmentAtOffset(Offset)); }
Addr.getElementType() returned what ended up with the CT->isPointerTy() being true.
This would seem to trace back to the AST side of things:
Stmt FunctionDecl::getBody(const FunctionDecl &Definition) const { if (!hasBody(Definition)) return nullptr;
if (Definition->Body) return Definition->Body.get(getASTContext().getExternalSource());
return nullptr; }
So. . .
class PPC32TargetInfo : public PPCTargetInfo {
public:
. . .
BuiltinVaListKind getBuiltinVaListKind() const override {
// This is the ELF definition, and is overridden by the Darwin sub-target
return TargetInfo::PowerABIBuiltinVaList;
}
};
. . .
class DarwinPPC32TargetInfo : public DarwinTargetInfo
Full backtrace Backtrace summary (full backtrace attached):
Thanks. The reduced test case also compiles with
clang -cc1 -triple ppc64-apple-macosx -S pr33108-reduced-1.cpp
I notice. Only the default (32bit) powerpc version fails.
Reduced test case:
// clang -cc1 -triple powerpc-apple-macosx -S pr33108-reduced-1.cpp void b() { builtin_va_list a; builtin_va_arg(a, int); }
It seems that the '-apple-macosx' suffix is needed to trigger the assertion. Using 'powerpc-freebsd' or 'powerpc-linux' does not trigger it.
Mark and/or Krzysztof, any clues as to the cause of this assertion?
This reproduces with trunk r303291, and actually gives an assertion:
Assertion failed: (Ty && "Invalid GetElementPtrInst indices for type!"), function checkGEPType, file include/llvm/IR/Instructions.h, line 835.
I'm reducing the test case now.
File that causes crash is too large to upload after precompile, and so is available here http://cunningham.homeunix.com/~cunningh/qstring-2a7643.cpp.zip
assigned to @kparzysz-quic
Linked patch is for darwin ppc which was dropped
Extended Description
crash during compilation of qt4-mac 4.8.7