[cfe-dev] var-arg handling

Robert Lytton robert at xmos.com
Tue Aug 13 03:28:20 PDT 2013


Hi,

Currently the XCore target passes the va_arg IR instruction to the back-end to handle
- using the default DefaultABIInfo.
However, this does mean that aggregate types are not handled.

I assume to support aggregate types, I must lower them within clang.
The question is should I:
    1. lower all types;
    2.  just the aggregate types, passing all other types as var_arg instructions.

On the surface, lowering all types does seem to allow better optimization - but may be this points to lack else where.

Example code to to both (viz XCORE_USE_INST_VAR_ARG) is below & suitable patch+tests attached.
Any comments on the correct way to handle var args welcome.
Thank you

Robert

//#define XCORE_USE_INST_VAR_ARG
llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
                                       CodeGenFunction &CGF) const {
  ABIArgInfo AI = classifyArgumentType(Ty);

#ifdef XCORE_USE_INST_VAR_ARG
  if (AI.getKind() != ABIArgInfo::Indirect)
    return 0; // use built in 'va_arg' instruction
#endif

  CGBuilderTy &Builder = CGF.Builder;
  llvm::Type *ArgTy = CGT.ConvertType(Ty);
  if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
    AI.setCoerceToType(ArgTy);

  // handle the VAList
  llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr,
                                                       CGF.Int8PtrPtrTy, "ap");
  llvm::Value *AP = Builder.CreateLoad(VAListAddrAsBPP, "indirect");
  llvm::Value *APN = Builder.CreateConstGEP1_32(AP, 4, "ap.next");
  Builder.CreateStore(APN, VAListAddrAsBPP);

  // handle the argument
  llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
#ifdef XCORE_USE_INST_VAR_ARG
  llvm::Value *ArgAddr;
  ArgAddr = Builder.CreateBitCast(AP, llvm::PointerType::getUnqual(ArgPtrTy),
                                  "indirect");
  ArgAddr = Builder.CreateLoad(ArgAddr, "arg");
  return Builder.CreatePointerCast(ArgAddr, ArgPtrTy, "arg");
#else
  switch (AI.getKind()) {
  default:
  case ABIArgInfo::Expand:
  case ABIArgInfo::Extend:
    llvm_unreachable("Unsupported ABI kind for va_arg");
  case ABIArgInfo::Ignore:
    return llvm::UndefValue::get(ArgPtrTy);
  case ABIArgInfo::Direct:
    return Builder.CreatePointerCast(AP, ArgPtrTy, "arg");
  case ABIArgInfo::Indirect:
    llvm::Value *ArgAddr;
    ArgAddr = Builder.CreateBitCast(AP, llvm::PointerType::getUnqual(ArgPtrTy),
                                    "indirect");
    ArgAddr = Builder.CreateLoad(ArgAddr, "arg");
    return Builder.CreatePointerCast(ArgAddr, ArgPtrTy, "arg");
  }
#endif
}


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130813/33aab318/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PatchVararg
Type: application/octet-stream
Size: 6587 bytes
Desc: PatchVararg
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130813/33aab318/attachment.obj>


More information about the cfe-dev mailing list