Build enough support for aggregates to be able to compile this:
void test(int A, _Complex float Y) {
_Complex float X;
X = X;
}
llvm-svn: 39669
This commit is contained in:
parent
3e3a1e9cda
commit
09153c0a8c
|
|
@ -231,7 +231,16 @@ RValue CodeGenFunction::EmitLoadOfLValue(const Expr *E) {
|
|||
|
||||
// FIXME: this is silly and obviously wrong for non-scalars.
|
||||
assert(!LV.isBitfield());
|
||||
return RValue::get(Builder.CreateLoad(LV.getAddress(), "tmp"));
|
||||
llvm::Value *Ptr = LV.getAddress();
|
||||
const llvm::Type *EltTy =
|
||||
cast<llvm::PointerType>(Ptr->getType())->getElementType();
|
||||
|
||||
// Simple scalar l-value.
|
||||
if (EltTy->isFirstClassType())
|
||||
return RValue::get(Builder.CreateLoad(Ptr, "tmp"));
|
||||
|
||||
// Otherwise, we have an aggregate lvalue.
|
||||
return RValue::getAggregate(Ptr);
|
||||
}
|
||||
|
||||
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
|
||||
|
|
@ -239,20 +248,43 @@ RValue CodeGenFunction::EmitLoadOfLValue(const Expr *E) {
|
|||
/// is 'Ty'.
|
||||
void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
|
||||
QualType Ty) {
|
||||
// FIXME: This is obviously bogus.
|
||||
assert(!Dst.isBitfield() && "FIXME: Don't support store to bitfield yet");
|
||||
assert(Src.isScalar() && "FIXME: Don't support store of aggregate yet");
|
||||
|
||||
// TODO: Handle volatility etc.
|
||||
llvm::Value *Addr = Dst.getAddress();
|
||||
llvm::Value *DstAddr = Dst.getAddress();
|
||||
if (Src.isScalar()) {
|
||||
// FIXME: Handle volatility etc.
|
||||
const llvm::Type *SrcTy = Src.getVal()->getType();
|
||||
const llvm::Type *AddrTy =
|
||||
cast<llvm::PointerType>(Addr->getType())->getElementType();
|
||||
cast<llvm::PointerType>(DstAddr->getType())->getElementType();
|
||||
|
||||
if (AddrTy != SrcTy)
|
||||
Addr = Builder.CreateBitCast(Addr, llvm::PointerType::get(SrcTy),
|
||||
DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy),
|
||||
"storetmp");
|
||||
Builder.CreateStore(Src.getVal(), Addr);
|
||||
Builder.CreateStore(Src.getVal(), DstAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Aggregate assignment turns into llvm.memcpy.
|
||||
const llvm::Type *SBP = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
llvm::Value *SrcAddr = Src.getAggregateAddr();
|
||||
|
||||
if (DstAddr->getType() != SBP)
|
||||
DstAddr = Builder.CreateBitCast(DstAddr, SBP, "tmp");
|
||||
if (SrcAddr->getType() != SBP)
|
||||
SrcAddr = Builder.CreateBitCast(SrcAddr, SBP, "tmp");
|
||||
|
||||
unsigned Align = 1; // FIXME: Compute type alignments.
|
||||
unsigned Size = 1234; // FIXME: Compute type sizes.
|
||||
|
||||
// FIXME: Handle variable sized types.
|
||||
const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth);
|
||||
llvm::Value *SizeVal = llvm::ConstantInt::get(IntPtr, Size);
|
||||
|
||||
llvm::Value *MemCpyOps[4] = {
|
||||
DstAddr, SrcAddr, SizeVal,llvm::ConstantInt::get(llvm::Type::Int32Ty, Align)
|
||||
};
|
||||
|
||||
Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, 4);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -402,7 +434,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) {
|
|||
if (ArgVal.isScalar())
|
||||
Args.push_back(ArgVal.getVal());
|
||||
else // Pass by-address. FIXME: Set attribute bit on call.
|
||||
Args.push_back(ArgVal.getAggregateVal());
|
||||
Args.push_back(ArgVal.getAggregateAddr());
|
||||
}
|
||||
|
||||
llvm::Value *V = Builder.CreateCall(Callee, &Args[0], Args.size());
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ class RValue {
|
|||
// TODO: Encode this into the low bit of pointer for more efficient
|
||||
// return-by-value.
|
||||
bool IsAggregate;
|
||||
|
||||
// FIXME: Aggregate rvalues need to retain information about whether they are
|
||||
// volatile or not.
|
||||
public:
|
||||
|
||||
bool isAggregate() const { return IsAggregate; }
|
||||
|
|
@ -79,8 +82,8 @@ public:
|
|||
return V;
|
||||
}
|
||||
|
||||
/// getAggregateVal() - Return the Value* of the address of the aggregate.
|
||||
llvm::Value *getAggregateVal() const {
|
||||
/// getAggregateAddr() - Return the Value* of the address of the aggregate.
|
||||
llvm::Value *getAggregateAddr() const {
|
||||
assert(isAggregate() && "Not an aggregate!");
|
||||
return V;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
#include "CodeGenFunction.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
|
|
@ -51,3 +53,16 @@ void CodeGenModule::EmitFunction(FunctionDecl *FD) {
|
|||
if (FD->getBody())
|
||||
CodeGenFunction(*this).GenerateCode(FD);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Function *CodeGenModule::getMemCpyFn() {
|
||||
if (MemCpyFn) return MemCpyFn;
|
||||
llvm::Intrinsic::ID IID;
|
||||
switch (Context.Target.getPointerWidth(SourceLocation())) {
|
||||
default: assert(0 && "Unknown ptr width");
|
||||
case 32: IID = llvm::Intrinsic::memcpy_i32; break;
|
||||
case 64: IID = llvm::Intrinsic::memcpy_i64; break;
|
||||
}
|
||||
return MemCpyFn = llvm::Intrinsic::getDeclaration(&TheModule, IID);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
namespace llvm {
|
||||
class Module;
|
||||
class Constant;
|
||||
class Function;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -36,6 +37,7 @@ class CodeGenModule {
|
|||
llvm::Module &TheModule;
|
||||
CodeGenTypes Types;
|
||||
|
||||
llvm::Function *MemCpyFn;
|
||||
llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
|
||||
public:
|
||||
CodeGenModule(ASTContext &C, llvm::Module &M);
|
||||
|
|
@ -46,6 +48,8 @@ public:
|
|||
|
||||
llvm::Constant *GetAddrOfGlobalDecl(const Decl *D);
|
||||
|
||||
llvm::Function *getMemCpyFn();
|
||||
|
||||
void EmitFunction(FunctionDecl *FD);
|
||||
|
||||
void PrintStats() {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue