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.
|
// FIXME: this is silly and obviously wrong for non-scalars.
|
||||||
assert(!LV.isBitfield());
|
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
|
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
|
||||||
|
|
@ -239,20 +248,43 @@ RValue CodeGenFunction::EmitLoadOfLValue(const Expr *E) {
|
||||||
/// is 'Ty'.
|
/// is 'Ty'.
|
||||||
void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
|
void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
|
||||||
QualType Ty) {
|
QualType Ty) {
|
||||||
// FIXME: This is obviously bogus.
|
|
||||||
assert(!Dst.isBitfield() && "FIXME: Don't support store to bitfield yet");
|
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 *DstAddr = Dst.getAddress();
|
||||||
llvm::Value *Addr = Dst.getAddress();
|
if (Src.isScalar()) {
|
||||||
const llvm::Type *SrcTy = Src.getVal()->getType();
|
// FIXME: Handle volatility etc.
|
||||||
const llvm::Type *AddrTy =
|
const llvm::Type *SrcTy = Src.getVal()->getType();
|
||||||
cast<llvm::PointerType>(Addr->getType())->getElementType();
|
const llvm::Type *AddrTy =
|
||||||
|
cast<llvm::PointerType>(DstAddr->getType())->getElementType();
|
||||||
|
|
||||||
|
if (AddrTy != SrcTy)
|
||||||
|
DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy),
|
||||||
|
"storetmp");
|
||||||
|
Builder.CreateStore(Src.getVal(), DstAddr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (AddrTy != SrcTy)
|
// Aggregate assignment turns into llvm.memcpy.
|
||||||
Addr = Builder.CreateBitCast(Addr, llvm::PointerType::get(SrcTy),
|
const llvm::Type *SBP = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||||
"storetmp");
|
llvm::Value *SrcAddr = Src.getAggregateAddr();
|
||||||
Builder.CreateStore(Src.getVal(), Addr);
|
|
||||||
|
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())
|
if (ArgVal.isScalar())
|
||||||
Args.push_back(ArgVal.getVal());
|
Args.push_back(ArgVal.getVal());
|
||||||
else // Pass by-address. FIXME: Set attribute bit on call.
|
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());
|
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
|
// TODO: Encode this into the low bit of pointer for more efficient
|
||||||
// return-by-value.
|
// return-by-value.
|
||||||
bool IsAggregate;
|
bool IsAggregate;
|
||||||
|
|
||||||
|
// FIXME: Aggregate rvalues need to retain information about whether they are
|
||||||
|
// volatile or not.
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool isAggregate() const { return IsAggregate; }
|
bool isAggregate() const { return IsAggregate; }
|
||||||
|
|
@ -79,8 +82,8 @@ public:
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getAggregateVal() - Return the Value* of the address of the aggregate.
|
/// getAggregateAddr() - Return the Value* of the address of the aggregate.
|
||||||
llvm::Value *getAggregateVal() const {
|
llvm::Value *getAggregateAddr() const {
|
||||||
assert(isAggregate() && "Not an aggregate!");
|
assert(isAggregate() && "Not an aggregate!");
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,11 @@
|
||||||
#include "CodeGenFunction.h"
|
#include "CodeGenFunction.h"
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
|
#include "clang/Basic/TargetInfo.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/GlobalVariable.h"
|
#include "llvm/GlobalVariable.h"
|
||||||
|
#include "llvm/Intrinsics.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace CodeGen;
|
using namespace CodeGen;
|
||||||
|
|
||||||
|
|
@ -51,3 +53,16 @@ void CodeGenModule::EmitFunction(FunctionDecl *FD) {
|
||||||
if (FD->getBody())
|
if (FD->getBody())
|
||||||
CodeGenFunction(*this).GenerateCode(FD);
|
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 {
|
namespace llvm {
|
||||||
class Module;
|
class Module;
|
||||||
class Constant;
|
class Constant;
|
||||||
|
class Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
@ -36,6 +37,7 @@ class CodeGenModule {
|
||||||
llvm::Module &TheModule;
|
llvm::Module &TheModule;
|
||||||
CodeGenTypes Types;
|
CodeGenTypes Types;
|
||||||
|
|
||||||
|
llvm::Function *MemCpyFn;
|
||||||
llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
|
llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
|
||||||
public:
|
public:
|
||||||
CodeGenModule(ASTContext &C, llvm::Module &M);
|
CodeGenModule(ASTContext &C, llvm::Module &M);
|
||||||
|
|
@ -46,6 +48,8 @@ public:
|
||||||
|
|
||||||
llvm::Constant *GetAddrOfGlobalDecl(const Decl *D);
|
llvm::Constant *GetAddrOfGlobalDecl(const Decl *D);
|
||||||
|
|
||||||
|
llvm::Function *getMemCpyFn();
|
||||||
|
|
||||||
void EmitFunction(FunctionDecl *FD);
|
void EmitFunction(FunctionDecl *FD);
|
||||||
|
|
||||||
void PrintStats() {}
|
void PrintStats() {}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue