[LLVMdev] llvm-gcc Bug, Looking for Advice on Fix

David Greene
2007-04-20T16:36:54Z

Ok, I've tracked down the problem I've had bootstrapping
llvm-gcc.  The culprit is in TreeToLLVM::EmitMemCpy:

void TreeToLLVM::EmitMemCpy(Value *DestPtr, Value *SrcPtr, Value *Size,
                             unsigned Align) {
   const Type *SBP = PointerType::get(Type::Int8Ty);
   const Type *IntPtr = TD.getIntPtrType();
   Value *Ops[4] = {
     CastToType(Instruction::BitCast, DestPtr, SBP),
     CastToType(Instruction::BitCast, SrcPtr, SBP),
     CastToSIntType(Size, IntPtr),
     ConstantInt::get(Type::Int32Ty, Align)
   };

   new CallInst(Intrinsic::getDeclaration(TheModule,
                                          (IntPtr == Type::Int32Ty) ?
                                          Intrinsic::memcpy_i32 :
                                          Intrinsic::memcpy_i64),
	       Ops, 4, "", CurBB);
}

The problem is that Intrinsic::getDeclaration takes four
parameters but is only passed two:

Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
                                     unsigned numTys)

So it sees bogus data from Tys and numTys.  This probably works
in the official sources because the "Ops, 4" parameters to CallInst
just happen to be pushed on the stack in just the right place
for Intrinsic::getDeclaration.  But apparently our changes to llvm
here upset that delicate balance.

So the obvious fix is this:

   new CallInst(Intrinsic::getDeclaration(TheModule,
                                          (IntPtr == Type::Int32Ty) ?
                                          Intrinsic::memcpy_i32 :
                                          Intrinsic::memcpy_i64,
					 Ops, 4),
	       "", CurBB);

But when I try to build I get:

compiler/llvm-gcc/gcc/llvm-convert.cpp:1203: error: cannot convert
'llvm::Value**' to 'const llvm::Type**' for argument '3'
to
'llvm::Function* llvm::Intrinsic::getDeclaration(llvm::Module*,
llvm::Intrinsic::ID, const llvm::Type**, unsigned int)'

Ok, that makes sense.  It's an illegal conversion.  So my question is,
what's the right fix?  The current code uses this CallInst constructor:

CallInst::CallInst(Value *Func, Value* const *Args, unsigned NumArgs,
                    const std::string &Name, BasicBlock *InsertAtEnd)

What's the intent of the TreeToLLVM::EmitMemCpy code?  I don't know
enough about the gcc frontend to be sure.

I'll submit a patch as soon as I better understand what's being done
here.

                                       -Dave