ZarkoCA updated this revision to Diff 250772.
ZarkoCA added a comment.

Removed unrelated changes in aix-cc-abi.ll


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76130/new/

https://reviews.llvm.org/D76130

Files:
  clang/lib/Basic/Targets/PPC.h
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/aix-vararg.c
  llvm/lib/Target/PowerPC/PPCISelLowering.cpp
  llvm/test/CodeGen/PowerPC/aix-cc-abi-va_args-32.ll

Index: llvm/test/CodeGen/PowerPC/aix-cc-abi-va_args-32.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/aix-cc-abi-va_args-32.ll
@@ -0,0 +1,277 @@
+; RUN: llc -O2 -mtriple powerpc-ibm-aix-xcoff -stop-after=machine-cp -mattr=-altivec -verify-machineinstrs < %s | \
+; RUN: FileCheck --check-prefixes=CHECK,32BIT %s
+
+; RUN: llc -O2 -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec \
+; RUN:  -mtriple powerpc-ibm-aix-xcoff < %s | \
+; RUN: FileCheck --check-prefixes=CHECKASM,ASM32PWR4 %s
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind
+declare void @llvm.va_start(i8*) #2
+
+; Function Attrs: nounwind
+declare void @llvm.va_end(i8*) #2
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+@a = local_unnamed_addr global i32 1, align 4
+@b = local_unnamed_addr global i32 2, align 4
+@c = local_unnamed_addr global i32 3, align 4
+@d = local_unnamed_addr global i32 4, align 4
+@e = local_unnamed_addr global i32 5, align 4
+@f = local_unnamed_addr global i32 6, align 4
+@g = local_unnamed_addr global i32 7, align 4
+@h = local_unnamed_addr global i32 8, align 4
+@i = local_unnamed_addr global i32 9, align 4
+@j = local_unnamed_addr global i32 10, align 4
+
+; Function Attrs: nounwind
+define i32 @va_arg1(i32 %a, ...) local_unnamed_addr #0 {
+entry:
+  %arg = alloca i8*, align 4
+  %0 = bitcast i8** %arg to i8*
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #2
+  call void @llvm.va_start(i8* nonnull %0)
+  %cmp7 = icmp sgt i32 %a, 0
+  br i1 %cmp7, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  %argp.cur.pre = load i8*, i8** %arg, align 4
+  %min.iters.check = icmp eq i32 %a, 1
+  br i1 %min.iters.check, label %for.body.preheader15, label %vector.memcheck
+
+vector.memcheck:                                  ; preds = %for.body.preheader
+  %uglygep = getelementptr inbounds i8, i8* %0, i32 1
+  %1 = shl i32 %a, 2
+  %scevgep = getelementptr i8, i8* %argp.cur.pre, i32 %1
+  %bound0 = icmp ugt i8* %scevgep, %0
+  %bound1 = icmp ult i8* %argp.cur.pre, %uglygep
+  %found.conflict = and i1 %bound0, %bound1
+  br i1 %found.conflict, label %for.body.preheader15, label %vector.ph
+
+vector.ph:                                        ; preds = %vector.memcheck
+  %n.vec = and i32 %a, -2
+  %2 = shl i32 %n.vec, 2
+  %ind.end = getelementptr i8, i8* %argp.cur.pre, i32 %2
+  br label %vector.body
+
+vector.body:                                      ; preds = %vector.body, %vector.ph
+  %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
+  %vec.phi = phi i32 [ undef, %vector.ph ], [ %11, %vector.body ]
+  %vec.phi13 = phi i32 [ 0, %vector.ph ], [ %12, %vector.body ]
+  %3 = shl i32 %index, 2
+  %next.gep = getelementptr i8, i8* %argp.cur.pre, i32 %3
+  %4 = shl i32 %index, 2
+  %5 = or i32 %4, 4
+  %next.gep12 = getelementptr i8, i8* %argp.cur.pre, i32 %5
+  %6 = getelementptr inbounds i8, i8* %next.gep12, i32 4
+  %7 = bitcast i8* %next.gep to i32*
+  %8 = bitcast i8* %next.gep12 to i32*
+  %9 = load i32, i32* %7, align 4 
+  %10 = load i32, i32* %8, align 4
+  %11 = add i32 %9, %vec.phi
+  %12 = add i32 %10, %vec.phi13
+  %index.next = add i32 %index, 2
+  %13 = icmp eq i32 %index.next, %n.vec
+  br i1 %13, label %middle.block, label %vector.body
+
+middle.block:                                     ; preds = %vector.body
+  store i8* %6, i8** %arg, align 4
+  %bin.rdx = add i32 %12, %11
+  %cmp.n = icmp eq i32 %n.vec, %a
+  br i1 %cmp.n, label %for.end, label %for.body.preheader15
+
+for.body.preheader15:                             ; preds = %middle.block, %vector.memcheck, %for.body.preheader
+  %argp.cur.ph = phi i8* [ %argp.cur.pre, %vector.memcheck ], [ %argp.cur.pre, %for.body.preheader ], [ %ind.end, %middle.block ]
+  %total.09.ph = phi i32 [ undef, %vector.memcheck ], [ undef, %for.body.preheader ], [ %bin.rdx, %middle.block ]
+  %i.08.ph = phi i32 [ 0, %vector.memcheck ], [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader15, %for.body
+  %argp.cur = phi i8* [ %argp.next, %for.body ], [ %argp.cur.ph, %for.body.preheader15 ]
+  %total.09 = phi i32 [ %add, %for.body ], [ %total.09.ph, %for.body.preheader15 ]
+  %i.08 = phi i32 [ %inc, %for.body ], [ %i.08.ph, %for.body.preheader15 ]
+  %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
+  store i8* %argp.next, i8** %arg, align 4
+  %14 = bitcast i8* %argp.cur to i32*
+  %15 = load i32, i32* %14, align 4
+  %add = add nsw i32 %15, %total.09
+  %inc = add nuw nsw i32 %i.08, 1
+  %exitcond = icmp eq i32 %inc, %a
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %middle.block, %entry
+  %total.0.lcssa = phi i32 [ undef, %entry ], [ %bin.rdx, %middle.block ], [ %add, %for.body ]
+  call void @llvm.va_end(i8* nonnull %0)
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #2
+  ret i32 %total.0.lcssa
+}
+
+
+; 32BIT-LABEL:   name:            va_arg1
+; 32BIT-LABEL:   liveins:
+; 32BIT-DAG:      - { reg: '$r3', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r4', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r5', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r6', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r7', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r8', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r9', virtual-reg: '' }
+; 32BIT-DAG:      - { reg: '$r10', virtual-reg: '' }
+; 32BIT-LABEL:   fixedStack:
+; 32BIT-DAG:      - { id: 0, type: default, offset: 28, size: 4
+; 32BIT-LABEL:    body:             |
+; 32BIT-LABEL:     bb.0.entry:
+; 32BIT-DAG:        liveins: $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10
+; 32BIT-DAG:        renamable $cr0 = CMPWI renamable $r3, 1
+; 32BIT-DAG:        STW killed renamable $r4, 0, %fixed-stack.0 :: (store 4 into %fixed-stack.0)
+; 32BIT-DAG:        STW killed renamable $r5, 4, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 4)
+; 32BIT-DAG:        STW killed renamable $r6, 8, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG:        STW killed renamable $r7, 12, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG:        STW killed renamable $r8, 16, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG:        STW killed renamable $r9, 20, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG:        STW killed renamable $r10, 24, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG:        renamable $r[[SCRATHREG:[0-9]+]] = ADDI %fixed-stack.0, 0
+; 32BIT-DAG:        STW killed renamable $r[[SCRATHREG:[0-9]+]], 0, %stack.0.arg :: (store 4 into %ir.0)
+
+; ASM32PWR4-LABEL:     .va_arg1:
+; ASM32PWR4-DAG:       cmpwi	3, 1
+; ASM32PWR4-DAG:       stw 4, 28(1)
+; ASM32PWR4-DAG:       stw 5, 32(1)
+; ASM32PWR4-DAG:       stw 6, 36(1)
+; ASM32PWR4-DAG:       stw 7, 40(1)
+; ASM32PWR4-DAG:       stw 8, 44(1)
+; ASM32PWR4-DAG:       stw 9, 48(1)
+; ASM32PWR4-DAG:       stw 10, 52(1)
+; ASM32PWR4-DAG:       stw [[SCRATCHREG:[0-9]+]], -4(1)
+; ASM32PWR4-DAG:       addi [[SCRATCHREG:[0-9]+]], 1, 28
+; ASM32PWR4-DAG:       blt	0, LBB0_8
+
+
+define i32 @va_arg2(i32 %one, i32 %two, i32 %three, i32 %four, i32 %five, i32 %six, i32 %seven, i32 %eight, ...) local_unnamed_addr #0 {
+entry:
+  %arg = alloca i8*, align 4
+  %0 = bitcast i8** %arg to i8*
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #2
+  call void @llvm.va_start(i8* nonnull %0)
+  %add = add nsw i32 %two, %one
+  %add2 = add nsw i32 %add, %three
+  %add3 = add nsw i32 %add2, %four
+  %add4 = add nsw i32 %add3, %five
+  %add5 = add nsw i32 %add4, %six
+  %add6 = add nsw i32 %add5, %seven
+  %add7 = add nsw i32 %add6, %eight
+  %cmp15 = icmp sgt i32 %eight, 0
+  br i1 %cmp15, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  %argp.cur.pre = load i8*, i8** %arg, align 4
+  %min.iters.check = icmp eq i32 %eight, 1
+  br i1 %min.iters.check, label %for.body.preheader23, label %vector.memcheck
+
+vector.memcheck:                                  ; preds = %for.body.preheader
+  %uglygep = getelementptr inbounds i8, i8* %0, i32 1
+  %1 = shl i32 %eight, 2
+  %scevgep = getelementptr i8, i8* %argp.cur.pre, i32 %1
+  %bound0 = icmp ugt i8* %scevgep, %0
+  %bound1 = icmp ult i8* %argp.cur.pre, %uglygep
+  %found.conflict = and i1 %bound0, %bound1
+  br i1 %found.conflict, label %for.body.preheader23, label %vector.ph
+
+vector.ph:                                        ; preds = %vector.memcheck
+  %n.vec = and i32 %eight, -2
+  %2 = shl i32 %n.vec, 2
+  %ind.end = getelementptr i8, i8* %argp.cur.pre, i32 %2
+  br label %vector.body
+
+vector.body:                                      ; preds = %vector.body, %vector.ph
+  %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
+  %vec.phi = phi i32 [ %add7, %vector.ph ], [ %11, %vector.body ]
+  %vec.phi21 = phi i32 [ 0, %vector.ph ], [ %12, %vector.body ]
+  %3 = shl i32 %index, 2
+  %next.gep = getelementptr i8, i8* %argp.cur.pre, i32 %3
+  %4 = shl i32 %index, 2
+  %5 = or i32 %4, 4
+  %next.gep20 = getelementptr i8, i8* %argp.cur.pre, i32 %5
+  %6 = getelementptr inbounds i8, i8* %next.gep20, i32 4
+  %7 = bitcast i8* %next.gep to i32*
+  %8 = bitcast i8* %next.gep20 to i32*
+  %9 = load i32, i32* %7, align 4
+  %10 = load i32, i32* %8, align 4
+  %11 = add i32 %9, %vec.phi
+  %12 = add i32 %10, %vec.phi21
+  %index.next = add i32 %index, 2
+  %13 = icmp eq i32 %index.next, %n.vec
+  br i1 %13, label %middle.block, label %vector.body
+
+middle.block:                                     ; preds = %vector.body
+  store i8* %6, i8** %arg, align 4
+  %bin.rdx = add i32 %12, %11
+  %cmp.n = icmp eq i32 %n.vec, %eight
+  br i1 %cmp.n, label %for.end, label %for.body.preheader23
+
+for.body.preheader23:                             ; preds = %middle.block, %vector.memcheck, %for.body.preheader
+  %argp.cur.ph = phi i8* [ %argp.cur.pre, %vector.memcheck ], [ %argp.cur.pre, %for.body.preheader ], [ %ind.end, %middle.block ]
+  %total.017.ph = phi i32 [ %add7, %vector.memcheck ], [ %add7, %for.body.preheader ], [ %bin.rdx, %middle.block ]
+  %i.016.ph = phi i32 [ 0, %vector.memcheck ], [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader23, %for.body
+  %argp.cur = phi i8* [ %argp.next, %for.body ], [ %argp.cur.ph, %for.body.preheader23 ]
+  %total.017 = phi i32 [ %add8, %for.body ], [ %total.017.ph, %for.body.preheader23 ]
+  %i.016 = phi i32 [ %inc, %for.body ], [ %i.016.ph, %for.body.preheader23 ]
+  %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
+  store i8* %argp.next, i8** %arg, align 4
+  %14 = bitcast i8* %argp.cur to i32*
+  %15 = load i32, i32* %14, align 4
+  %add8 = add nsw i32 %15, %total.017
+  %inc = add nuw nsw i32 %i.016, 1
+  %exitcond = icmp eq i32 %inc, %eight
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %middle.block, %entry
+  %total.0.lcssa = phi i32 [ %add7, %entry ], [ %bin.rdx, %middle.block ], [ %add8, %for.body ]
+  call void @llvm.va_end(i8* nonnull %0)
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #2
+  ret i32 %total.0.lcssa
+}
+
+; 32BIT-LABEL:   name:            va_arg2
+; 32BIT-LABEL:   liveins:
+; 32BIT-DAG:     - { reg: '$r3', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r4', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r5', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r6', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r7', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r8', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r9', virtual-reg: '' }
+; 32BIT-DAG:     - { reg: '$r10', virtual-reg: '' }
+; 32BIT-LABEL:   fixedStack:
+; 32BIT-DAG:     - { id: 0, type: default, offset: 56, size: 4
+; 32BIT-LABEL:   body:             |
+; 32BIT-LABEL:     bb.0.entry:
+; 32BIT-DAG:       liveins: $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10
+; 32BIT-DAG:       STW killed renamable $r11, 0, %stack.0.arg :: (store 4 into %ir.0)
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r4, killed renamable $r3
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r5
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r6
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r7
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r8
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r9
+; 32BIT-DAG:       renamable $cr0 = CMPWI renamable $r10, 1
+; 32BIT-DAG:       renamable $r3 = nsw ADD4 killed renamable $r3, renamable $r10
+; 32BIT-DAG:       renamable $r11 = ADDI %fixed-stack.0, 0
+
+; ASM32PWR4-LABEL: .va_arg2:
+; ASM32PWR4-DAG:   add 3, 4, 3
+; ASM32PWR4-DAG:   add 3, 3, 5
+; ASM32PWR4-DAG:   add 3, 3, 6
+; ASM32PWR4-DAG:   add 3, 3, 7
+; ASM32PWR4-DAG:   add 3, 3, 8
+; ASM32PWR4-DAG:   add 3, 3, 9
+; ASM32PWR4-DAG:   add 3, 3, 10
+; ASM32PWR4-DAG:   cmpwi 10, 1
+; ASM32PWR4-DAG:   addi [[SCRATCHREG:[0-9]+]], 1, 56
+; ASM32PWR4-DAG:   stw [[SCRATCHREG:[0-9]+]], -4(1)
+
Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3238,7 +3238,7 @@
 
   SDLoc dl(Op);
 
-  if (Subtarget.isPPC64()) {
+  if (Subtarget.isPPC64() || Subtarget.isAIXABI()) {
     // vastart just stores the address of the VarArgsFrameIndex slot into the
     // memory location argument.
     SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
@@ -6967,9 +6967,6 @@
           CallConv == CallingConv::Fast) &&
          "Unexpected calling convention!");
 
-  if (isVarArg)
-    report_fatal_error("This call type is unimplemented on AIX.");
-
   if (getTargetMachine().Options.GuaranteedTailCallOpt)
     report_fatal_error("Tail call support is unimplemented on AIX.");
 
@@ -6982,11 +6979,15 @@
     report_fatal_error("QPX support is not supported on AIX.");
 
   const bool IsPPC64 = Subtarget.isPPC64();
+  if (IsPPC64 && isVarArg)
+    report_fatal_error("This call type is unimplemented on 63-bit AIX.");
+
   const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
 
   // Assign locations to all of the incoming arguments.
   SmallVector<CCValAssign, 16> ArgLocs;
   MachineFunction &MF = DAG.getMachineFunction();
+  MachineFrameInfo &MFI = MF.getFrameInfo();
   CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
 
   const EVT PtrVT = getPointerTy(MF.getDataLayout());
@@ -7013,7 +7014,7 @@
     if (VA.isMemLoc() && VA.needsCustom())
       continue;
 
-    if (VA.isRegLoc()) {
+    if (VA.isRegLoc() && !VA.needsCustom()) {
       MVT::SimpleValueType SVT = ValVT.getSimpleVT().SimpleTy;
       unsigned VReg =
           MF.addLiveIn(VA.getLocReg(), getRegClassForSVT(SVT, IsPPC64));
@@ -7025,42 +7026,87 @@
       }
       InVals.push_back(ArgValue);
       continue;
+    } else if (VA.isMemLoc()) {
+      const unsigned LocSize = LocVT.getStoreSize();
+      const unsigned ValSize = ValVT.getStoreSize();
+      assert((ValSize <= LocSize) &&
+             "Object size is larger than size of MemLoc");
+      int CurArgOffset = VA.getLocMemOffset();
+      // Objects are right-justified because AIX is big-endian.
+      if (LocSize > ValSize)
+        CurArgOffset += LocSize - ValSize;
+      MachineFrameInfo &MFI = MF.getFrameInfo();
+      // Potential tail calls could cause overwriting of argument stack slots.
+      const bool IsImmutable =
+          !(getTargetMachine().Options.GuaranteedTailCallOpt &&
+            (CallConv == CallingConv::Fast));
+      int FI = MFI.CreateFixedObject(ValSize, CurArgOffset, IsImmutable);
+      SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
+      SDValue ArgValue =
+          DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
+      InVals.push_back(ArgValue);
+    }
+  }
+    // On AIX a minimum of 8 words is saved to the parameter save area.
+    const unsigned MinParameterSaveArea = 8 * PtrByteSize;
+    // Area that is at least reserved in the caller of this function.
+    unsigned CallerReservedArea = std::max(CCInfo.getNextStackOffset(),
+                                           LinkageSize + MinParameterSaveArea);
+
+    // Set the size that is at least reserved in caller of this function. Tail
+    // call optimized function's reserved stack space needs to be aligned so
+    // that taking the difference between two stack areas will result in an
+    // aligned stack.
+    CallerReservedArea =
+        EnsureStackAlignment(Subtarget.getFrameLowering(), CallerReservedArea);
+    PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
+    FuncInfo->setMinReservedArea(CallerReservedArea);
+
+    SmallVector<SDValue, 8> MemOps;
+
+    if (isVarArg) {
+
+      const static MCPhysReg GPR_32[] = {PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+                                         PPC::R7, PPC::R8, PPC::R9, PPC::R10};
+
+      const static MCPhysReg GPR_64[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,
+                                         PPC::X7, PPC::X8, PPC::X9, PPC::X10};
+
+      const unsigned NumGPArgRegs = array_lengthof(IsPPC64 ? GPR_64 : GPR_32);
+
+      FuncInfo->setVarArgsNumGPR(
+          CCInfo.getFirstUnallocated(IsPPC64 ? GPR_64 : GPR_32));
+      FuncInfo->setVarArgsFrameIndex(MFI.CreateFixedObject(
+          PtrByteSize, CCInfo.getNextStackOffset(), true));
+      SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
+      // The fixed integer arguments of a variadic function are stored to the
+      // VarArgsFrameIndex on the stack so that they may be loaded by
+      // dereferencing the result of va_next.
+      for (unsigned GPRIndex =
+               (CCInfo.getNextStackOffset() - LinkageSize) / PtrByteSize;
+           GPRIndex < NumGPArgRegs; ++GPRIndex) {
+        unsigned VReg = MF.getRegInfo().getLiveInVirtReg(
+            IsPPC64 ? GPR_64[GPRIndex] : GPR_32[GPRIndex]);
+        if (!VReg) {
+          if (IsPPC64)
+            VReg = MF.addLiveIn(GPR_64[GPRIndex], &PPC::G8RCRegClass);
+          else
+            VReg = MF.addLiveIn(GPR_32[GPRIndex], &PPC::GPRCRegClass);
+        }
+        SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
+        SDValue Store =
+            DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo());
+        MemOps.push_back(Store);
+        // Increment the address for the next argument to store.
+        SDValue PtrOff = DAG.getConstant(PtrByteSize, dl, PtrVT);
+        FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff);
+      }
     }
 
-    const unsigned LocSize = LocVT.getStoreSize();
-    const unsigned ValSize = ValVT.getStoreSize();
-    assert((ValSize <= LocSize) && "Object size is larger than size of MemLoc");
-    int CurArgOffset = VA.getLocMemOffset();
-    // Objects are right-justified because AIX is big-endian.
-    if (LocSize > ValSize)
-      CurArgOffset += LocSize - ValSize;
-    MachineFrameInfo &MFI = MF.getFrameInfo();
-    // Potential tail calls could cause overwriting of argument stack slots.
-    const bool IsImmutable =
-        !(getTargetMachine().Options.GuaranteedTailCallOpt &&
-          (CallConv == CallingConv::Fast));
-    int FI = MFI.CreateFixedObject(ValSize, CurArgOffset, IsImmutable);
-    SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
-    SDValue ArgValue = DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
-    InVals.push_back(ArgValue);
-  }
-
-  // On AIX a minimum of 8 words is saved to the parameter save area.
-  const unsigned MinParameterSaveArea = 8 * PtrByteSize;
-  // Area that is at least reserved in the caller of this function.
-  unsigned CallerReservedArea =
-      std::max(CCInfo.getNextStackOffset(), LinkageSize + MinParameterSaveArea);
-
-  // Set the size that is at least reserved in caller of this function. Tail
-  // call optimized function's reserved stack space needs to be aligned so
-  // that taking the difference between two stack areas will result in an
-  // aligned stack.
-  CallerReservedArea =
-      EnsureStackAlignment(Subtarget.getFrameLowering(), CallerReservedArea);
-  PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
-  FuncInfo->setMinReservedArea(CallerReservedArea);
+    if (!MemOps.empty())
+      Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
 
-  return Chain;
+    return Chain;
 }
 
 SDValue PPCTargetLowering::LowerCall_AIX(
Index: clang/test/CodeGen/aix-vararg.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aix-vararg.c
@@ -0,0 +1,30 @@
+// REQUIRES: powerpc-registered-target
+// REQUIRES: asserts
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s --check-prefix=32BIT
+#include <stdarg.h>
+
+void aix_varg(int a, ...) {
+  va_list arg;
+  va_start(arg, a);
+  va_arg(arg, int);
+  va_end(arg);
+}
+
+// 32BIT:           define void @aix_varg(i32 %a, ...) #0 {
+// 32BIT:           entry:
+// 32BIT-NEXT:        %a.addr = alloca i32, align 4
+// 32BIT-NEXT:        %arg = alloca i8*, align 4
+// 32BIT-NEXT:        store i32 %a, i32* %a.addr, align 4
+// 32BIT-NEXT:        %arg1 = bitcast i8** %arg to i8*
+// 32BIT-NEXT:        call void @llvm.va_start(i8* %arg1)
+// 32BIT-NEXT:        %argp.cur = load i8*, i8** %arg, align 4
+// 32BIT-NEXT:        %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
+// 32BIT-NEXT:        store i8* %argp.next, i8** %arg, align 4
+// 32BIT-NEXT:        %0 = bitcast i8* %argp.cur to i32*
+// 32BIT-NEXT:        %1 = load i32, i32* %0, align 4
+// 32BIT-NEXT:        %arg2 = bitcast i8** %arg to i8*
+// 32BIT-NEXT:        call void @llvm.va_end(i8* %arg2)
+// 32BIT-NEXT:        ret void
+// 32BIT-NEXT:      }
+// 32BIT:            declare void @llvm.va_start(i8*)
+// 32BIT:            declare void @llvm.va_end(i8*)
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -4229,7 +4229,10 @@
 // DefaultABIInfo::EmitVAArg.
 Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
                                       QualType Ty) const {
-  if (getTarget().getTriple().isOSDarwin()) {
+  // TODO: Add AIX ABI Info.  Currently we are relying on PPC32_SVR4_ABIInfo to
+  // emit correct VAArg.
+  if (getTarget().getTriple().isOSDarwin() ||
+      getTarget().getTriple().isOSAIX()) {
     auto TI = getContext().getTypeInfoInChars(Ty);
     TI.second = getParamTypeAlignment(Ty);
 
Index: clang/lib/Basic/Targets/PPC.h
===================================================================
--- clang/lib/Basic/Targets/PPC.h
+++ clang/lib/Basic/Targets/PPC.h
@@ -369,7 +369,8 @@
   }
 
   BuiltinVaListKind getBuiltinVaListKind() const override {
-    // This is the ELF definition, and is overridden by the Darwin sub-target
+    // This is the ELF definition, and is overridden by the Darwin and AIX
+    // sub-target
     return TargetInfo::PowerABIBuiltinVaList;
   }
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to