Why isn't __builtin_va_arg an intrinsics?

Hello,

Each TargetABI, /clang/lib/CodeGen/TargetInfo.cpp, should define a target-specific IR.

This causes to generate a target-specific IR, which prevents IR from having target-neutrality.

For example,

On X86,

llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,

CodeGenFunction &CGF) const {

llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());

llvm::Type *BPP = llvm::PointerType::getUnqual(BP);

CGBuilderTy &Builder = CGF.Builder;

llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,

“ap”);

llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, “ap.cur”);

llvm::Type *PTy =

llvm::PointerType::getUnqual(CGF.ConvertType(Ty));

llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);

uint64_t Offset =

llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);

llvm::Value *NextAddr =

Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),

“ap.next”);

Builder.CreateStore(NextAddr, VAListAddrAsBPP);

return AddrTyped;

}

However, on ARM, the highlighted code is arm-specific, which breaks the portability.

llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,

CodeGenFunction &CGF) const {

¡¦

// Handle address alignment for type alignment > 32 bits

uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;

if (TyAlign > 4) {

assert((TyAlign & (TyAlign - 1)) == 0 &&

"Alignment is not power of 2!");

llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);

AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));

AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));

Addr = Builder.CreateIntToPtr(AddrAsInt, BP);

}

¡¦

}

Any other builtins, __builtin_va_start, __builtin_va_end, and __builtin_va_copy, are of instrinsics, which would be translated to machine code later.

Is there any reason why __builtin_va_arg is generated in IR, not in an intrinsic?

Sincerely yours,

Jaemin Park.