diff options
author | Chris Lattner <sabre@nondot.org> | 2008-03-15 23:59:48 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-03-15 23:59:48 +0000 |
commit | 7a51313d8a0a358bb92eb5dbf8fd846b7c48e7fe (patch) | |
tree | f34d8e560a6abbae809b7dbee85606becf47dfd0 /clang/lib/CodeGen | |
parent | d3f989ccd302d53e327c030347313fbd8d23a344 (diff) | |
download | bcm5719-llvm-7a51313d8a0a358bb92eb5dbf8fd846b7c48e7fe.tar.gz bcm5719-llvm-7a51313d8a0a358bb92eb5dbf8fd846b7c48e7fe.zip |
Make a major restructuring of the clang tree: introduce a top-level
lib dir and move all the libraries into it. This follows the main
llvm tree, and allows the libraries to be built in parallel. The
top level now enforces that all the libs are built before Driver,
but we don't care what order the libs are built in. This speeds
up parallel builds, particularly incremental ones.
llvm-svn: 48402
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 486 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 163 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 615 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 337 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 542 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 627 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 1185 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 25 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 97 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCRuntime.h | 47 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 776 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 182 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 486 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 509 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 129 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 580 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 165 | ||||
-rw-r--r-- | clang/lib/CodeGen/Makefile | 23 | ||||
-rw-r--r-- | clang/lib/CodeGen/ModuleBuilder.cpp | 104 |
19 files changed, 7078 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp new file mode 100644 index 00000000000..83c5e60475c --- /dev/null +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -0,0 +1,486 @@ +//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Builtin calls as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Builtins.h" +#include "clang/AST/Expr.h" +#include "clang/AST/TargetBuiltins.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +using namespace clang; +using namespace CodeGen; +using namespace llvm; + +RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { + switch (BuiltinID) { + default: { + if (getContext().BuiltinInfo.isLibFunction(BuiltinID)) + return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID), + E->getCallee()->getType(), E->arg_begin(), + E->getNumArgs()); + + // See if we have a target specific intrinsic. + Intrinsic::ID IntrinsicID; + const char *TargetPrefix = Target.getTargetPrefix(); + const char *BuiltinName = getContext().BuiltinInfo.GetName(BuiltinID); +#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN +#include "llvm/Intrinsics.gen" +#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN + + if (IntrinsicID != Intrinsic::not_intrinsic) { + SmallVector<Value*, 16> Args; + + Function *F = CGM.getIntrinsic(IntrinsicID); + const llvm::FunctionType *FTy = F->getFunctionType(); + + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { + Value *ArgValue = EmitScalarExpr(E->getArg(i)); + + // If the intrinsic arg type is different from the builtin arg type + // we need to do a bit cast. + const llvm::Type *PTy = FTy->getParamType(i); + if (PTy != ArgValue->getType()) { + assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) && + "Must be able to losslessly bit cast to param"); + ArgValue = Builder.CreateBitCast(ArgValue, PTy); + } + + Args.push_back(ArgValue); + } + + Value *V = Builder.CreateCall(F, &Args[0], &Args[0] + Args.size()); + QualType BuiltinRetType = E->getType(); + + const llvm::Type *RetTy = llvm::Type::VoidTy; + if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType); + + if (RetTy != V->getType()) { + assert(V->getType()->canLosslesslyBitCastTo(RetTy) && + "Must be able to losslessly bit cast result type"); + V = Builder.CreateBitCast(V, RetTy); + } + + return RValue::get(V); + } + + // See if we have a target specific builtin that needs to be lowered. + Value *V = 0; + + if (strcmp(TargetPrefix, "x86") == 0) + V = EmitX86BuiltinExpr(BuiltinID, E); + else if (strcmp(TargetPrefix, "ppc") == 0) + V = EmitPPCBuiltinExpr(BuiltinID, E); + + if (V) + return RValue::get(V); + + WarnUnsupported(E, "builtin function"); + + // Unknown builtin, for now just dump it out and return undef. + if (hasAggregateLLVMType(E->getType())) + return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType()))); + return RValue::get(UndefValue::get(ConvertType(E->getType()))); + } + case Builtin::BI__builtin___CFStringMakeConstantString: { + const Expr *Arg = E->getArg(0); + + while (1) { + if (const ParenExpr *PE = dyn_cast<ParenExpr>(Arg)) + Arg = PE->getSubExpr(); + else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Arg)) + Arg = CE->getSubExpr(); + else + break; + } + + const StringLiteral *Literal = cast<StringLiteral>(Arg); + std::string S(Literal->getStrData(), Literal->getByteLength()); + + return RValue::get(CGM.GetAddrOfConstantCFString(S)); + } + case Builtin::BI__builtin_va_start: + case Builtin::BI__builtin_va_end: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + const llvm::Type *DestType = + llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + if (ArgValue->getType() != DestType) + ArgValue = Builder.CreateBitCast(ArgValue, DestType, + ArgValue->getNameStart()); + + Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_start) ? + Intrinsic::vastart : Intrinsic::vaend; + return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue)); + } + case Builtin::BI__builtin_va_copy: { + // FIXME: This does not yet handle architectures where va_list is a struct. + Value *DstPtr = EmitScalarExpr(E->getArg(0)); + Value *SrcValue = EmitScalarExpr(E->getArg(1)); + + Value *SrcPtr = CreateTempAlloca(SrcValue->getType(), "dst_ptr"); + + // FIXME: Volatile + Builder.CreateStore(SrcValue, SrcPtr, false); + + const llvm::Type *Type = + llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + + DstPtr = Builder.CreateBitCast(DstPtr, Type); + SrcPtr = Builder.CreateBitCast(SrcPtr, Type); + Value *Args[] = { DstPtr, SrcPtr }; + return RValue::get(Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy), + &Args[0], &Args[2])); + } + case Builtin::BI__builtin_classify_type: { + APSInt Result(32); + if (!E->isBuiltinClassifyType(Result)) + assert(0 && "Expr not __builtin_classify_type!"); + return RValue::get(ConstantInt::get(Result)); + } + case Builtin::BI__builtin_constant_p: { + APSInt Result(32); + // FIXME: Analyze the parameter and check if it is a constant. + Result = 0; + return RValue::get(ConstantInt::get(Result)); + } + case Builtin::BI__builtin_abs: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + + llvm::BinaryOperator *NegOp = + Builder.CreateNeg(ArgValue, (ArgValue->getName() + "neg").c_str()); + Value *CmpResult = + Builder.CreateICmpSGE(ArgValue, NegOp->getOperand(0), "abscond"); + Value *Result = + Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs"); + + return RValue::get(Result); + } + case Builtin::BI__builtin_ctz: + case Builtin::BI__builtin_ctzl: + case Builtin::BI__builtin_ctzll: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + + const llvm::Type *ArgType = ArgValue->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1); + + const llvm::Type *ResultType = ConvertType(E->getType()); + Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); + if (Result->getType() != ResultType) + Result = Builder.CreateIntCast(Result, ResultType, "cast"); + return RValue::get(Result); + } + case Builtin::BI__builtin_expect: + return RValue::get(EmitScalarExpr(E->getArg(0))); + case Builtin::BI__builtin_bswap32: + case Builtin::BI__builtin_bswap64: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + const llvm::Type *ArgType = ArgValue->getType(); + Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1); + return RValue::get(Builder.CreateCall(F, ArgValue, "tmp")); + } + case Builtin::BI__builtin_inff: { + APFloat f(APFloat::IEEEsingle, APFloat::fcInfinity, false); + return RValue::get(ConstantFP::get(llvm::Type::FloatTy, f)); + } + case Builtin::BI__builtin_huge_val: + case Builtin::BI__builtin_inf: + // FIXME: mapping long double onto double. + case Builtin::BI__builtin_infl: { + APFloat f(APFloat::IEEEdouble, APFloat::fcInfinity, false); + return RValue::get(ConstantFP::get(llvm::Type::DoubleTy, f)); + } + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: { + // Ordered comparisons: we know the arguments to these are matching scalar + // floating point values. + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + + switch (BuiltinID) { + default: assert(0 && "Unknown ordered comparison"); + case Builtin::BI__builtin_isgreater: + LHS = Builder.CreateFCmpOGT(LHS, RHS, "cmp"); + break; + case Builtin::BI__builtin_isgreaterequal: + LHS = Builder.CreateFCmpOGE(LHS, RHS, "cmp"); + break; + case Builtin::BI__builtin_isless: + LHS = Builder.CreateFCmpOLT(LHS, RHS, "cmp"); + break; + case Builtin::BI__builtin_islessequal: + LHS = Builder.CreateFCmpOLE(LHS, RHS, "cmp"); + break; + case Builtin::BI__builtin_islessgreater: + LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp"); + break; + case Builtin::BI__builtin_isunordered: + LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp"); + break; + } + // ZExt bool to int type. + return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()), + "tmp")); + } + case Builtin::BI__builtin_alloca: + return RValue::get(Builder.CreateAlloca(llvm::Type::Int8Ty, + EmitScalarExpr(E->getArg(0)), + "tmp")); + } + return RValue::get(0); +} + +Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + + llvm::SmallVector<Value*, 4> Ops; + + for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) + Ops.push_back(EmitScalarExpr(E->getArg(i))); + + switch (BuiltinID) { + default: return 0; + case X86::BI__builtin_ia32_mulps: + return Builder.CreateMul(Ops[0], Ops[1], "mulps"); + case X86::BI__builtin_ia32_pand: + return Builder.CreateAnd(Ops[0], Ops[1], "pand"); + case X86::BI__builtin_ia32_por: + return Builder.CreateAnd(Ops[0], Ops[1], "por"); + case X86::BI__builtin_ia32_pxor: + return Builder.CreateAnd(Ops[0], Ops[1], "pxor"); + case X86::BI__builtin_ia32_pandn: { + Ops[0] = Builder.CreateNot(Ops[0], "tmp"); + return Builder.CreateAnd(Ops[0], Ops[1], "pandn"); + } + case X86::BI__builtin_ia32_paddb: + case X86::BI__builtin_ia32_paddd: + case X86::BI__builtin_ia32_paddq: + case X86::BI__builtin_ia32_paddw: + case X86::BI__builtin_ia32_addps: + return Builder.CreateAdd(Ops[0], Ops[1], "add"); + case X86::BI__builtin_ia32_psubb: + case X86::BI__builtin_ia32_psubd: + case X86::BI__builtin_ia32_psubq: + case X86::BI__builtin_ia32_psubw: + case X86::BI__builtin_ia32_subps: + return Builder.CreateSub(Ops[0], Ops[1], "sub"); + case X86::BI__builtin_ia32_divps: + return Builder.CreateFDiv(Ops[0], Ops[1], "divps"); + case X86::BI__builtin_ia32_pmullw: + return Builder.CreateMul(Ops[0], Ops[1], "pmul"); + case X86::BI__builtin_ia32_punpckhbw: + return EmitShuffleVector(Ops[0], Ops[1], 4, 12, 5, 13, 6, 14, 7, 15, + "punpckhbw"); + case X86::BI__builtin_ia32_punpckhwd: + return EmitShuffleVector(Ops[0], Ops[1], 2, 6, 3, 7, "punpckhwd"); + case X86::BI__builtin_ia32_punpckhdq: + return EmitShuffleVector(Ops[0], Ops[1], 1, 3, "punpckhdq"); + case X86::BI__builtin_ia32_punpcklbw: + return EmitShuffleVector(Ops[0], Ops[1], 0, 8, 1, 9, 2, 10, 3, 11, + "punpcklbw"); + case X86::BI__builtin_ia32_punpcklwd: + return EmitShuffleVector(Ops[0], Ops[1], 0, 4, 1, 5, "punpcklwd"); + case X86::BI__builtin_ia32_punpckldq: + return EmitShuffleVector(Ops[0], Ops[1], 0, 2, "punpckldq"); + case X86::BI__builtin_ia32_pslldi: + case X86::BI__builtin_ia32_psllqi: + case X86::BI__builtin_ia32_psllwi: + case X86::BI__builtin_ia32_psradi: + case X86::BI__builtin_ia32_psrawi: + case X86::BI__builtin_ia32_psrldi: + case X86::BI__builtin_ia32_psrlqi: + case X86::BI__builtin_ia32_psrlwi: { + Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::Int64Ty, "zext"); + const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::Int64Ty, 1); + Ops[1] = Builder.CreateBitCast(Ops[1], Ty, "bitcast"); + const char *name = 0; + Intrinsic::ID ID = Intrinsic::not_intrinsic; + + switch (BuiltinID) { + default: assert(0 && "Unsupported shift intrinsic!"); + case X86::BI__builtin_ia32_pslldi: + name = "pslldi"; + ID = Intrinsic::x86_mmx_psll_d; + break; + case X86::BI__builtin_ia32_psllqi: + name = "psllqi"; + ID = Intrinsic::x86_mmx_psll_q; + break; + case X86::BI__builtin_ia32_psllwi: + name = "psllwi"; + ID = Intrinsic::x86_mmx_psll_w; + break; + case X86::BI__builtin_ia32_psradi: + name = "psradi"; + ID = Intrinsic::x86_mmx_psra_d; + break; + case X86::BI__builtin_ia32_psrawi: + name = "psrawi"; + ID = Intrinsic::x86_mmx_psra_w; + break; + case X86::BI__builtin_ia32_psrldi: + name = "psrldi"; + ID = Intrinsic::x86_mmx_psrl_d; + break; + case X86::BI__builtin_ia32_psrlqi: + name = "psrlqi"; + ID = Intrinsic::x86_mmx_psrl_q; + break; + case X86::BI__builtin_ia32_psrlwi: + name = "psrlwi"; + ID = Intrinsic::x86_mmx_psrl_w; + break; + } + llvm::Function *F = CGM.getIntrinsic(ID); + return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); + } + case X86::BI__builtin_ia32_pshufd: { + unsigned i = cast<ConstantInt>(Ops[1])->getZExtValue(); + return EmitShuffleVector(Ops[0], Ops[0], + i & 0x3, (i & 0xc) >> 2, + (i & 0x30) >> 4, (i & 0xc0) >> 6, + "pshufd"); + } + case X86::BI__builtin_ia32_vec_init_v4hi: + case X86::BI__builtin_ia32_vec_init_v8qi: + case X86::BI__builtin_ia32_vec_init_v2si: + return EmitVector(&Ops[0], Ops.size()); + case X86::BI__builtin_ia32_vec_ext_v2si: + return Builder.CreateExtractElement(Ops[0], Ops[1], "result"); + case X86::BI__builtin_ia32_cmpordss: + case X86::BI__builtin_ia32_cmpunordss: + case X86::BI__builtin_ia32_cmpeqss: + case X86::BI__builtin_ia32_cmpltss: + case X86::BI__builtin_ia32_cmpless: + case X86::BI__builtin_ia32_cmpneqss: + case X86::BI__builtin_ia32_cmpnltss: + case X86::BI__builtin_ia32_cmpnless: { + unsigned i = 0; + const char *name = 0; + switch (BuiltinID) { + default: assert(0 && "Unknown compare builtin!"); + case X86::BI__builtin_ia32_cmpeqss: + i = 0; + name = "cmpeqss"; + break; + case X86::BI__builtin_ia32_cmpltss: + i = 1; + name = "cmpltss"; + break; + case X86::BI__builtin_ia32_cmpless: + i = 2; + name = "cmpless"; + break; + case X86::BI__builtin_ia32_cmpunordss: + i = 3; + name = "cmpunordss"; + break; + case X86::BI__builtin_ia32_cmpneqss: + i = 4; + name = "cmpneqss"; + break; + case X86::BI__builtin_ia32_cmpnltss: + i = 5; + name = "cmpntlss"; + break; + case X86::BI__builtin_ia32_cmpnless: + i = 6; + name = "cmpnless"; + break; + case X86::BI__builtin_ia32_cmpordss: + i = 7; + name = "cmpordss"; + break; + } + + Ops.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, i)); + llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ss); + return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); + } + case X86::BI__builtin_ia32_cmpordps: + case X86::BI__builtin_ia32_cmpunordps: + case X86::BI__builtin_ia32_cmpeqps: + case X86::BI__builtin_ia32_cmpltps: + case X86::BI__builtin_ia32_cmpleps: + case X86::BI__builtin_ia32_cmpneqps: + case X86::BI__builtin_ia32_cmpngtps: + case X86::BI__builtin_ia32_cmpnltps: + case X86::BI__builtin_ia32_cmpgtps: + case X86::BI__builtin_ia32_cmpgeps: + case X86::BI__builtin_ia32_cmpngeps: + case X86::BI__builtin_ia32_cmpnleps: { + unsigned i = 0; + const char *name = 0; + bool ShouldSwap = false; + switch (BuiltinID) { + default: assert(0 && "Unknown compare builtin!"); + case X86::BI__builtin_ia32_cmpeqps: i = 0; name = "cmpeqps"; break; + case X86::BI__builtin_ia32_cmpltps: i = 1; name = "cmpltps"; break; + case X86::BI__builtin_ia32_cmpleps: i = 2; name = "cmpleps"; break; + case X86::BI__builtin_ia32_cmpunordps: i = 3; name = "cmpunordps"; break; + case X86::BI__builtin_ia32_cmpneqps: i = 4; name = "cmpneqps"; break; + case X86::BI__builtin_ia32_cmpnltps: i = 5; name = "cmpntlps"; break; + case X86::BI__builtin_ia32_cmpnleps: i = 6; name = "cmpnleps"; break; + case X86::BI__builtin_ia32_cmpordps: i = 7; name = "cmpordps"; break; + case X86::BI__builtin_ia32_cmpgtps: + ShouldSwap = true; + i = 1; + name = "cmpgtps"; + break; + case X86::BI__builtin_ia32_cmpgeps: + i = 2; + name = "cmpgeps"; + ShouldSwap = true; + break; + case X86::BI__builtin_ia32_cmpngtps: + i = 5; + name = "cmpngtps"; + ShouldSwap = true; + break; + case X86::BI__builtin_ia32_cmpngeps: + i = 6; + name = "cmpngeps"; + ShouldSwap = true; + break; + } + + if (ShouldSwap) + std::swap(Ops[0], Ops[1]); + + Ops.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, i)); + llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ps); + return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); + } + case X86::BI__builtin_ia32_movss: + return EmitShuffleVector(Ops[0], Ops[1], 4, 1, 2, 3, "movss"); + case X86::BI__builtin_ia32_shufps: + unsigned i = cast<ConstantInt>(Ops[2])->getZExtValue(); + return EmitShuffleVector(Ops[0], Ops[1], + i & 0x3, (i & 0xc) >> 2, + ((i & 0x30) >> 4) + 4, + ((i & 0x60) >> 6) + 4, "shufps"); + } +} + +Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + default: return 0; + } +} diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp new file mode 100644 index 00000000000..c80cecc76ee --- /dev/null +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -0,0 +1,163 @@ +//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Decl nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Type.h" +using namespace clang; +using namespace CodeGen; + + +void CodeGenFunction::EmitDecl(const Decl &D) { + switch (D.getKind()) { + default: assert(0 && "Unknown decl kind!"); + case Decl::FileVar: + assert(0 && "Should not see file-scope variables inside a function!"); + case Decl::ParmVar: + assert(0 && "Parmdecls should not be in declstmts!"); + case Decl::Typedef: // typedef int X; + case Decl::Function: // void X(); + case Decl::Struct: // struct X; + case Decl::Union: // union X; + case Decl::Class: // class X; + case Decl::Enum: // enum X; + // None of these decls require codegen support. + return; + + case Decl::BlockVar: + return EmitBlockVarDecl(cast<BlockVarDecl>(D)); + case Decl::EnumConstant: + return EmitEnumConstantDecl(cast<EnumConstantDecl>(D)); + } +} + +void CodeGenFunction::EmitEnumConstantDecl(const EnumConstantDecl &D) { + assert(0 && "FIXME: Enum constant decls not implemented yet!"); +} + +/// EmitBlockVarDecl - This method handles emission of any variable declaration +/// inside a function, including static vars etc. +void CodeGenFunction::EmitBlockVarDecl(const BlockVarDecl &D) { + switch (D.getStorageClass()) { + case VarDecl::Static: + return EmitStaticBlockVarDecl(D); + case VarDecl::Extern: + // Don't emit it now, allow it to be emitted lazily on its first use. + return; + default: + assert((D.getStorageClass() == VarDecl::None || + D.getStorageClass() == VarDecl::Auto || + D.getStorageClass() == VarDecl::Register) && + "Unknown storage class"); + return EmitLocalBlockVarDecl(D); + } +} + +void CodeGenFunction::EmitStaticBlockVarDecl(const BlockVarDecl &D) { + QualType Ty = D.getCanonicalType(); + assert(Ty->isConstantSizeType() && "VLAs can't be static"); + + llvm::Value *&DMEntry = LocalDeclMap[&D]; + assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); + + const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty); + llvm::Constant *Init = 0; + if (D.getInit() == 0) { + Init = llvm::Constant::getNullValue(LTy); + } else { + Init = CGM.EmitConstantExpr(D.getInit(), this); + } + + assert(Init && "Unable to create initialiser for static decl"); + + std::string ContextName; + if (CurFuncDecl) + ContextName = CurFuncDecl->getName(); + else + assert(0 && "Unknown context for block var decl"); // FIXME Handle objc. + + DMEntry = + new llvm::GlobalVariable(LTy, false, + llvm::GlobalValue::InternalLinkage, + Init, ContextName + "." + D.getName(), + &CGM.getModule(), 0, + Ty.getAddressSpace()); + +} + +/// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a +/// variable declaration with auto, register, or no storage class specifier. +/// These turn into simple stack objects. +void CodeGenFunction::EmitLocalBlockVarDecl(const BlockVarDecl &D) { + QualType Ty = D.getCanonicalType(); + + llvm::Value *DeclPtr; + if (Ty->isConstantSizeType()) { + // A normal fixed sized variable becomes an alloca in the entry block. + const llvm::Type *LTy = ConvertType(Ty); + // TODO: Alignment + DeclPtr = CreateTempAlloca(LTy, D.getName()); + } else { + // TODO: Create a dynamic alloca. + assert(0 && "FIXME: Local VLAs not implemented yet"); + } + + llvm::Value *&DMEntry = LocalDeclMap[&D]; + assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); + DMEntry = DeclPtr; + + // If this local has an initializer, emit it now. + if (const Expr *Init = D.getInit()) { + if (!hasAggregateLLVMType(Init->getType())) { + llvm::Value *V = EmitScalarExpr(Init); + Builder.CreateStore(V, DeclPtr, D.getType().isVolatileQualified()); + } else if (Init->getType()->isComplexType()) { + EmitComplexExprIntoAddr(Init, DeclPtr, D.getType().isVolatileQualified()); + } else { + EmitAggExpr(Init, DeclPtr, D.getType().isVolatileQualified()); + } + } +} + +/// Emit an alloca for the specified parameter and set up LocalDeclMap. +void CodeGenFunction::EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg) { + QualType Ty = D.getCanonicalType(); + + llvm::Value *DeclPtr; + if (!Ty->isConstantSizeType()) { + // Variable sized values always are passed by-reference. + DeclPtr = Arg; + } else { + // A fixed sized first class variable becomes an alloca in the entry block. + const llvm::Type *LTy = ConvertType(Ty); + if (LTy->isFirstClassType()) { + // TODO: Alignment + DeclPtr = new llvm::AllocaInst(LTy, 0, std::string(D.getName())+".addr", + AllocaInsertPt); + + // Store the initial value into the alloca. + Builder.CreateStore(Arg, DeclPtr); + } else { + // Otherwise, if this is an aggregate, just use the input pointer. + DeclPtr = Arg; + } + Arg->setName(D.getName()); + } + + llvm::Value *&DMEntry = LocalDeclMap[&D]; + assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); + DMEntry = DeclPtr; +} + diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp new file mode 100644 index 00000000000..932a5c5da8b --- /dev/null +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -0,0 +1,615 @@ +//===--- CGExpr.cpp - Emit LLVM Code from Expressions ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Expr nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Support/MathExtras.h" +using namespace clang; +using namespace CodeGen; + +//===--------------------------------------------------------------------===// +// Miscellaneous Helper Methods +//===--------------------------------------------------------------------===// + +/// CreateTempAlloca - This creates a alloca and inserts it into the entry +/// block. +llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty, + const char *Name) { + return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt); +} + +/// EvaluateExprAsBool - Perform the usual unary conversions on the specified +/// expression and compare the result against zero, returning an Int1Ty value. +llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { + QualType BoolTy = getContext().BoolTy; + if (!E->getType()->isComplexType()) + return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy); + + return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(),BoolTy); +} + +/// EmitAnyExpr - Emit code to compute the specified expression which can have +/// any type. The result is returned as an RValue struct. If this is an +/// aggregate expression, the aggloc/agglocvolatile arguments indicate where +/// the result should be returned. +RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, + bool isAggLocVolatile) { + if (!hasAggregateLLVMType(E->getType())) + return RValue::get(EmitScalarExpr(E)); + else if (E->getType()->isComplexType()) + return RValue::getComplex(EmitComplexExpr(E)); + + EmitAggExpr(E, AggLoc, isAggLocVolatile); + return RValue::getAggregate(AggLoc); +} + + +//===----------------------------------------------------------------------===// +// LValue Expression Emission +//===----------------------------------------------------------------------===// + +/// EmitLValue - Emit code to compute a designator that specifies the location +/// of the expression. +/// +/// This can return one of two things: a simple address or a bitfield +/// reference. In either case, the LLVM Value* in the LValue structure is +/// guaranteed to be an LLVM pointer type. +/// +/// If this returns a bitfield reference, nothing about the pointee type of +/// the LLVM value is known: For example, it may not be a pointer to an +/// integer. +/// +/// If this returns a normal address, and if the lvalue's C type is fixed +/// size, this method guarantees that the returned pointer type will point to +/// an LLVM type of the same size of the lvalue's type. If the lvalue has a +/// variable length type, this is not possible. +/// +LValue CodeGenFunction::EmitLValue(const Expr *E) { + switch (E->getStmtClass()) { + default: { + WarnUnsupported(E, "l-value expression"); + llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); + return LValue::MakeAddr(llvm::UndefValue::get(Ty)); + } + + case Expr::CallExprClass: return EmitCallExprLValue(cast<CallExpr>(E)); + case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E)); + case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); + case Expr::PreDefinedExprClass: + return EmitPreDefinedLValue(cast<PreDefinedExpr>(E)); + case Expr::StringLiteralClass: + return EmitStringLiteralLValue(cast<StringLiteral>(E)); + + case Expr::UnaryOperatorClass: + return EmitUnaryOpLValue(cast<UnaryOperator>(E)); + case Expr::ArraySubscriptExprClass: + return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); + case Expr::OCUVectorElementExprClass: + return EmitOCUVectorElementExpr(cast<OCUVectorElementExpr>(E)); + case Expr::MemberExprClass: return EmitMemberExpr(cast<MemberExpr>(E)); + } +} + +/// EmitLoadOfLValue - Given an expression that represents a value lvalue, +/// this method emits the address of the lvalue, then loads the result as an +/// rvalue, returning the rvalue. +RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { + if (LV.isSimple()) { + llvm::Value *Ptr = LV.getAddress(); + const llvm::Type *EltTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + + // Simple scalar l-value. + if (EltTy->isFirstClassType()) { + llvm::Value *V = Builder.CreateLoad(Ptr, "tmp"); + + // Bool can have different representation in memory than in registers. + if (ExprType->isBooleanType()) { + if (V->getType() != llvm::Type::Int1Ty) + V = Builder.CreateTrunc(V, llvm::Type::Int1Ty, "tobool"); + } + + return RValue::get(V); + } + + assert(ExprType->isFunctionType() && "Unknown scalar value"); + return RValue::get(Ptr); + } + + if (LV.isVectorElt()) { + llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), "tmp"); + return RValue::get(Builder.CreateExtractElement(Vec, LV.getVectorIdx(), + "vecext")); + } + + // If this is a reference to a subset of the elements of a vector, either + // shuffle the input or extract/insert them as appropriate. + if (LV.isOCUVectorElt()) + return EmitLoadOfOCUElementLValue(LV, ExprType); + + if (LV.isBitfield()) + return EmitLoadOfBitfieldLValue(LV, ExprType); + + assert(0 && "Unknown LValue type!"); + //an invalid RValue, but the assert will + //ensure that this point is never reached + return RValue(); +} + +RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, + QualType ExprType) { + llvm::Value *Ptr = LV.getBitfieldAddr(); + const llvm::Type *EltTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + unsigned EltTySize = EltTy->getPrimitiveSizeInBits(); + unsigned short BitfieldSize = LV.getBitfieldSize(); + unsigned short EndBit = LV.getBitfieldStartBit() + BitfieldSize; + + llvm::Value *V = Builder.CreateLoad(Ptr, "tmp"); + + llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - EndBit); + V = Builder.CreateShl(V, ShAmt, "tmp"); + + ShAmt = llvm::ConstantInt::get(EltTy, EltTySize - BitfieldSize); + V = LV.isBitfieldSigned() ? + Builder.CreateAShr(V, ShAmt, "tmp") : + Builder.CreateLShr(V, ShAmt, "tmp"); + return RValue::get(V); +} + +// If this is a reference to a subset of the elements of a vector, either +// shuffle the input or extract/insert them as appropriate. +RValue CodeGenFunction::EmitLoadOfOCUElementLValue(LValue LV, + QualType ExprType) { + llvm::Value *Vec = Builder.CreateLoad(LV.getOCUVectorAddr(), "tmp"); + + unsigned EncFields = LV.getOCUVectorElts(); + + // If the result of the expression is a non-vector type, we must be + // extracting a single element. Just codegen as an extractelement. + const VectorType *ExprVT = ExprType->getAsVectorType(); + if (!ExprVT) { + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(0, EncFields); + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp")); + } + + // If the source and destination have the same number of elements, use a + // vector shuffle instead of insert/extracts. + unsigned NumResultElts = ExprVT->getNumElements(); + unsigned NumSourceElts = + cast<llvm::VectorType>(Vec->getType())->getNumElements(); + + if (NumResultElts == NumSourceElts) { + llvm::SmallVector<llvm::Constant*, 4> Mask; + for (unsigned i = 0; i != NumResultElts; ++i) { + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(i, EncFields); + Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx)); + } + + llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size()); + Vec = Builder.CreateShuffleVector(Vec, + llvm::UndefValue::get(Vec->getType()), + MaskV, "tmp"); + return RValue::get(Vec); + } + + // Start out with an undef of the result type. + llvm::Value *Result = llvm::UndefValue::get(ConvertType(ExprType)); + + // Extract/Insert each element of the result. + for (unsigned i = 0; i != NumResultElts; ++i) { + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(i, EncFields); + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + Elt = Builder.CreateExtractElement(Vec, Elt, "tmp"); + + llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Result = Builder.CreateInsertElement(Result, Elt, OutIdx, "tmp"); + } + + return RValue::get(Result); +} + + + +/// EmitStoreThroughLValue - Store the specified rvalue into the specified +/// lvalue, where both are guaranteed to the have the same type, and that type +/// is 'Ty'. +void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, + QualType Ty) { + if (!Dst.isSimple()) { + if (Dst.isVectorElt()) { + // Read/modify/write the vector, inserting the new element. + // FIXME: Volatility. + llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(), "tmp"); + Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(), + Dst.getVectorIdx(), "vecins"); + Builder.CreateStore(Vec, Dst.getVectorAddr()); + return; + } + + // If this is an update of elements of a vector, insert them as appropriate. + if (Dst.isOCUVectorElt()) + return EmitStoreThroughOCUComponentLValue(Src, Dst, Ty); + + if (Dst.isBitfield()) + return EmitStoreThroughBitfieldLValue(Src, Dst, Ty); + + assert(0 && "Unknown LValue type"); + } + + llvm::Value *DstAddr = Dst.getAddress(); + assert(Src.isScalar() && "Can't emit an agg store with this method"); + // FIXME: Handle volatility etc. + const llvm::Type *SrcTy = Src.getScalarVal()->getType(); + const llvm::PointerType *DstPtr = cast<llvm::PointerType>(DstAddr->getType()); + const llvm::Type *AddrTy = DstPtr->getElementType(); + unsigned AS = DstPtr->getAddressSpace(); + + if (AddrTy != SrcTy) + DstAddr = Builder.CreateBitCast(DstAddr, + llvm::PointerType::get(SrcTy, AS), + "storetmp"); + Builder.CreateStore(Src.getScalarVal(), DstAddr); +} + +void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, + QualType Ty) { + unsigned short StartBit = Dst.getBitfieldStartBit(); + unsigned short BitfieldSize = Dst.getBitfieldSize(); + llvm::Value *Ptr = Dst.getBitfieldAddr(); + const llvm::Type *EltTy = + cast<llvm::PointerType>(Ptr->getType())->getElementType(); + unsigned EltTySize = EltTy->getPrimitiveSizeInBits(); + + llvm::Value *NewVal = Src.getScalarVal(); + llvm::Value *OldVal = Builder.CreateLoad(Ptr, "tmp"); + + llvm::Value *ShAmt = llvm::ConstantInt::get(EltTy, StartBit); + NewVal = Builder.CreateShl(NewVal, ShAmt, "tmp"); + + llvm::Constant *Mask = llvm::ConstantInt::get( + llvm::APInt::getBitsSet(EltTySize, StartBit, + StartBit + BitfieldSize)); + + // Mask out any bits that shouldn't be set in the result. + NewVal = Builder.CreateAnd(NewVal, Mask, "tmp"); + + // Next, mask out the bits this bit-field should include from the old value. + Mask = llvm::ConstantExpr::getNot(Mask); + OldVal = Builder.CreateAnd(OldVal, Mask, "tmp"); + + // Finally, merge the two together and store it. + NewVal = Builder.CreateOr(OldVal, NewVal, "tmp"); + + Builder.CreateStore(NewVal, Ptr); +} + +void CodeGenFunction::EmitStoreThroughOCUComponentLValue(RValue Src, LValue Dst, + QualType Ty) { + // This access turns into a read/modify/write of the vector. Load the input + // value now. + llvm::Value *Vec = Builder.CreateLoad(Dst.getOCUVectorAddr(), "tmp"); + // FIXME: Volatility. + unsigned EncFields = Dst.getOCUVectorElts(); + + llvm::Value *SrcVal = Src.getScalarVal(); + + if (const VectorType *VTy = Ty->getAsVectorType()) { + unsigned NumSrcElts = VTy->getNumElements(); + + // Extract/Insert each element. + for (unsigned i = 0; i != NumSrcElts; ++i) { + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp"); + + unsigned Idx = OCUVectorElementExpr::getAccessedFieldNo(i, EncFields); + llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx); + Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp"); + } + } else { + // If the Src is a scalar (not a vector) it must be updating one element. + unsigned InIdx = OCUVectorElementExpr::getAccessedFieldNo(0, EncFields); + llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp"); + } + + Builder.CreateStore(Vec, Dst.getOCUVectorAddr()); +} + + +LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { + const ValueDecl *D = E->getDecl(); + if (isa<BlockVarDecl>(D) || isa<ParmVarDecl>(D)) { + const VarDecl *VD = cast<VarDecl>(D); + if (VD->getStorageClass() == VarDecl::Extern) + return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD, false)); + else { + llvm::Value *V = LocalDeclMap[D]; + assert(V && "BlockVarDecl not entered in LocalDeclMap?"); + return LValue::MakeAddr(V); + } + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + return LValue::MakeAddr(CGM.GetAddrOfFunctionDecl(FD, false)); + } else if (const FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) { + return LValue::MakeAddr(CGM.GetAddrOfGlobalVar(FVD, false)); + } + assert(0 && "Unimp declref"); + //an invalid LValue, but the assert will + //ensure that this point is never reached. + return LValue(); +} + +LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { + // __extension__ doesn't affect lvalue-ness. + if (E->getOpcode() == UnaryOperator::Extension) + return EmitLValue(E->getSubExpr()); + + switch (E->getOpcode()) { + default: assert(0 && "Unknown unary operator lvalue!"); + case UnaryOperator::Deref: + return LValue::MakeAddr(EmitScalarExpr(E->getSubExpr())); + case UnaryOperator::Real: + case UnaryOperator::Imag: + LValue LV = EmitLValue(E->getSubExpr()); + + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, + E->getOpcode() == UnaryOperator::Imag); + llvm::Value *Ops[] = {Zero, Idx}; + return LValue::MakeAddr(Builder.CreateGEP(LV.getAddress(), Ops, Ops+2, + "idx")); + } +} + +LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { + assert(!E->isWide() && "FIXME: Wide strings not supported yet!"); + const char *StrData = E->getStrData(); + unsigned Len = E->getByteLength(); + std::string StringLiteral(StrData, StrData+Len); + return LValue::MakeAddr(CGM.GetAddrOfConstantString(StringLiteral)); +} + +LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) { + std::string FunctionName(CurFuncDecl->getName()); + std::string GlobalVarName; + + switch (E->getIdentType()) { + default: + assert(0 && "unknown pre-defined ident type"); + case PreDefinedExpr::Func: + GlobalVarName = "__func__."; + break; + case PreDefinedExpr::Function: + GlobalVarName = "__FUNCTION__."; + break; + case PreDefinedExpr::PrettyFunction: + // FIXME:: Demangle C++ method names + GlobalVarName = "__PRETTY_FUNCTION__."; + break; + } + + GlobalVarName += CurFuncDecl->getName(); + + // FIXME: Can cache/reuse these within the module. + llvm::Constant *C=llvm::ConstantArray::get(FunctionName); + + // Create a global variable for this. + C = new llvm::GlobalVariable(C->getType(), true, + llvm::GlobalValue::InternalLinkage, + C, GlobalVarName, CurFn->getParent()); + return LValue::MakeAddr(C); +} + +LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { + // The index must always be an integer, which is not an aggregate. Emit it. + llvm::Value *Idx = EmitScalarExpr(E->getIdx()); + + // If the base is a vector type, then we are forming a vector element lvalue + // with this subscript. + if (E->getLHS()->getType()->isVectorType()) { + // Emit the vector as an lvalue to get its address. + LValue LHS = EmitLValue(E->getLHS()); + assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); + // FIXME: This should properly sign/zero/extend or truncate Idx to i32. + return LValue::MakeVectorElt(LHS.getAddress(), Idx); + } + + // The base must be a pointer, which is not an aggregate. Emit it. + llvm::Value *Base = EmitScalarExpr(E->getBase()); + + // Extend or truncate the index type to 32 or 64-bits. + QualType IdxTy = E->getIdx()->getType(); + bool IdxSigned = IdxTy->isSignedIntegerType(); + unsigned IdxBitwidth = cast<llvm::IntegerType>(Idx->getType())->getBitWidth(); + if (IdxBitwidth != LLVMPointerWidth) + Idx = Builder.CreateIntCast(Idx, llvm::IntegerType::get(LLVMPointerWidth), + IdxSigned, "idxprom"); + + // We know that the pointer points to a type of the correct size, unless the + // size is a VLA. + if (!E->getType()->isConstantSizeType()) + assert(0 && "VLA idx not implemented"); + return LValue::MakeAddr(Builder.CreateGEP(Base, Idx, "arrayidx")); +} + +LValue CodeGenFunction:: +EmitOCUVectorElementExpr(const OCUVectorElementExpr *E) { + // Emit the base vector as an l-value. + LValue Base = EmitLValue(E->getBase()); + assert(Base.isSimple() && "Can only subscript lvalue vectors here!"); + + return LValue::MakeOCUVectorElt(Base.getAddress(), + E->getEncodedElementAccess()); +} + +LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { + bool isUnion = false; + Expr *BaseExpr = E->getBase(); + llvm::Value *BaseValue = NULL; + + // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. + if (E->isArrow()) { + BaseValue = EmitScalarExpr(BaseExpr); + const PointerType *PTy = + cast<PointerType>(BaseExpr->getType().getCanonicalType()); + if (PTy->getPointeeType()->isUnionType()) + isUnion = true; + } + else { + LValue BaseLV = EmitLValue(BaseExpr); + // FIXME: this isn't right for bitfields. + BaseValue = BaseLV.getAddress(); + if (BaseExpr->getType()->isUnionType()) + isUnion = true; + } + + FieldDecl *Field = E->getMemberDecl(); + return EmitLValueForField(BaseValue, Field, isUnion); +} + +LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, + FieldDecl* Field, + bool isUnion) +{ + llvm::Value *V; + unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); + + if (Field->isBitField()) { + const llvm::Type * FieldTy = ConvertType(Field->getType()); + const llvm::PointerType * BaseTy = + cast<llvm::PointerType>(BaseValue->getType()); + unsigned AS = BaseTy->getAddressSpace(); + BaseValue = Builder.CreateBitCast(BaseValue, + llvm::PointerType::get(FieldTy, AS), + "tmp"); + V = Builder.CreateGEP(BaseValue, + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx), + "tmp"); + } else { + llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty), + llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) }; + V = Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp"); + } + // Match union field type. + if (isUnion) { + const llvm::Type * FieldTy = ConvertType(Field->getType()); + const llvm::PointerType * BaseTy = + cast<llvm::PointerType>(BaseValue->getType()); + if (FieldTy != BaseTy->getElementType()) { + unsigned AS = BaseTy->getAddressSpace(); + V = Builder.CreateBitCast(V, + llvm::PointerType::get(FieldTy, AS), + "tmp"); + } + } + + if (Field->isBitField()) { + CodeGenTypes::BitFieldInfo bitFieldInfo = + CGM.getTypes().getBitFieldInfo(Field); + return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size, + Field->getType()->isSignedIntegerType()); + } else + return LValue::MakeAddr(V); +} + +//===--------------------------------------------------------------------===// +// Expression Emission +//===--------------------------------------------------------------------===// + + +RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { + if (const ImplicitCastExpr *IcExpr = + dyn_cast<const ImplicitCastExpr>(E->getCallee())) + if (const DeclRefExpr *DRExpr = + dyn_cast<const DeclRefExpr>(IcExpr->getSubExpr())) + if (const FunctionDecl *FDecl = + dyn_cast<const FunctionDecl>(DRExpr->getDecl())) + if (unsigned builtinID = FDecl->getIdentifier()->getBuiltinID()) + return EmitBuiltinExpr(builtinID, E); + + llvm::Value *Callee = EmitScalarExpr(E->getCallee()); + return EmitCallExpr(Callee, E->getCallee()->getType(), + E->arg_begin(), E->getNumArgs()); +} + +RValue CodeGenFunction::EmitCallExpr(Expr *FnExpr, Expr *const *Args, + unsigned NumArgs) { + llvm::Value *Callee = EmitScalarExpr(FnExpr); + return EmitCallExpr(Callee, FnExpr->getType(), Args, NumArgs); +} + +LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { + // Can only get l-value for call expression returning aggregate type + RValue RV = EmitCallExpr(E); + return LValue::MakeAddr(RV.getAggregateAddr()); +} + +RValue CodeGenFunction::EmitCallExpr(llvm::Value *Callee, QualType FnType, + Expr *const *ArgExprs, unsigned NumArgs) { + // The callee type will always be a pointer to function type, get the function + // type. + FnType = cast<PointerType>(FnType.getCanonicalType())->getPointeeType(); + QualType ResultType = cast<FunctionType>(FnType)->getResultType(); + + llvm::SmallVector<llvm::Value*, 16> Args; + + // Handle struct-return functions by passing a pointer to the location that + // we would like to return into. + if (hasAggregateLLVMType(ResultType)) { + // Create a temporary alloca to hold the result of the call. :( + Args.push_back(CreateTempAlloca(ConvertType(ResultType))); + // FIXME: set the stret attribute on the argument. + } + + for (unsigned i = 0, e = NumArgs; i != e; ++i) { + QualType ArgTy = ArgExprs[i]->getType(); + + if (!hasAggregateLLVMType(ArgTy)) { + // Scalar argument is passed by-value. + Args.push_back(EmitScalarExpr(ArgExprs[i])); + } else if (ArgTy->isComplexType()) { + // Make a temporary alloca to pass the argument. + llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy)); + EmitComplexExprIntoAddr(ArgExprs[i], DestMem, false); + Args.push_back(DestMem); + } else { + llvm::Value *DestMem = CreateTempAlloca(ConvertType(ArgTy)); + EmitAggExpr(ArgExprs[i], DestMem, false); + Args.push_back(DestMem); + } + } + + llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size()); + if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee)) + CI->setCallingConv(F->getCallingConv()); + if (CI->getType() != llvm::Type::VoidTy) + CI->setName("call"); + else if (ResultType->isComplexType()) + return RValue::getComplex(LoadComplexFromAddr(Args[0], false)); + else if (hasAggregateLLVMType(ResultType)) + // Struct return. + return RValue::getAggregate(Args[0]); + else { + // void return. + assert(ResultType->isVoidType() && "Should only have a void expr here"); + CI = 0; + } + + return RValue::get(CI); +} diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp new file mode 100644 index 00000000000..325ac2109eb --- /dev/null +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -0,0 +1,337 @@ +//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Aggregate Expr nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Support/Compiler.h" +using namespace clang; +using namespace CodeGen; + +//===----------------------------------------------------------------------===// +// Aggregate Expression Emitter +//===----------------------------------------------------------------------===// + +namespace { +class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor<AggExprEmitter> { + CodeGenFunction &CGF; + llvm::LLVMFoldingBuilder &Builder; + llvm::Value *DestPtr; + bool VolatileDest; +public: + AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool volatileDest) + : CGF(cgf), Builder(CGF.Builder), + DestPtr(destPtr), VolatileDest(volatileDest) { + } + + //===--------------------------------------------------------------------===// + // Utilities + //===--------------------------------------------------------------------===// + + /// EmitAggLoadOfLValue - Given an expression with aggregate type that + /// represents a value lvalue, this method emits the address of the lvalue, + /// then loads the result into DestPtr. + void EmitAggLoadOfLValue(const Expr *E); + + void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, + QualType EltTy); + + void EmitAggregateClear(llvm::Value *DestPtr, QualType Ty); + + void EmitNonConstInit(InitListExpr *E); + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + void VisitStmt(Stmt *S) { + CGF.WarnUnsupported(S, "aggregate expression"); + } + void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); } + + // l-values. + void VisitDeclRefExpr(DeclRefExpr *DRE) { EmitAggLoadOfLValue(DRE); } + void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); } + void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); } + void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); } + + void VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + EmitAggLoadOfLValue(E); + } + + // Operators. + // case Expr::UnaryOperatorClass: + // case Expr::CastExprClass: + void VisitImplicitCastExpr(ImplicitCastExpr *E); + void VisitCallExpr(const CallExpr *E); + void VisitStmtExpr(const StmtExpr *E); + void VisitBinaryOperator(const BinaryOperator *BO); + void VisitBinAssign(const BinaryOperator *E); + void VisitOverloadExpr(const OverloadExpr *E); + + + void VisitConditionalOperator(const ConditionalOperator *CO); + void VisitInitListExpr(InitListExpr *E); + // case Expr::ChooseExprClass: + +}; +} // end anonymous namespace. + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +void AggExprEmitter::EmitAggregateClear(llvm::Value *DestPtr, QualType Ty) { + assert(!Ty->isComplexType() && "Shouldn't happen for complex"); + + // Aggregate assignment turns into llvm.memset. + const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + if (DestPtr->getType() != BP) + DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); + + // Get size and alignment info for this aggregate. + std::pair<uint64_t, unsigned> TypeInfo = CGF.getContext().getTypeInfo(Ty); + + // FIXME: Handle variable sized types. + const llvm::Type *IntPtr = llvm::IntegerType::get(CGF.LLVMPointerWidth); + + llvm::Value *MemSetOps[4] = { + DestPtr, + llvm::ConstantInt::getNullValue(llvm::Type::Int8Ty), + // TypeInfo.first describes size in bits. + llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), + llvm::ConstantInt::get(llvm::Type::Int32Ty, TypeInfo.second/8) + }; + + Builder.CreateCall(CGF.CGM.getMemSetFn(), MemSetOps, MemSetOps+4); +} + +void AggExprEmitter::EmitAggregateCopy(llvm::Value *DestPtr, + llvm::Value *SrcPtr, QualType Ty) { + assert(!Ty->isComplexType() && "Shouldn't happen for complex"); + + // Aggregate assignment turns into llvm.memcpy. + const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + if (DestPtr->getType() != BP) + DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); + if (SrcPtr->getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + + // Get size and alignment info for this aggregate. + std::pair<uint64_t, unsigned> TypeInfo = CGF.getContext().getTypeInfo(Ty); + + // FIXME: Handle variable sized types. + const llvm::Type *IntPtr = llvm::IntegerType::get(CGF.LLVMPointerWidth); + + llvm::Value *MemCpyOps[4] = { + DestPtr, SrcPtr, + // TypeInfo.first describes size in bits. + llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), + llvm::ConstantInt::get(llvm::Type::Int32Ty, TypeInfo.second/8) + }; + + Builder.CreateCall(CGF.CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4); +} + + +/// EmitAggLoadOfLValue - Given an expression with aggregate type that +/// represents a value lvalue, this method emits the address of the lvalue, +/// then loads the result into DestPtr. +void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { + LValue LV = CGF.EmitLValue(E); + assert(LV.isSimple() && "Can't have aggregate bitfield, vector, etc"); + llvm::Value *SrcPtr = LV.getAddress(); + + // If the result is ignored, don't copy from the value. + if (DestPtr == 0) + // FIXME: If the source is volatile, we must read from it. + return; + + EmitAggregateCopy(DestPtr, SrcPtr, E->getType()); +} + +//===----------------------------------------------------------------------===// +// Visitor Methods +//===----------------------------------------------------------------------===// + +void AggExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *E) +{ + QualType STy = E->getSubExpr()->getType().getCanonicalType(); + QualType Ty = E->getType().getCanonicalType(); + + assert(CGF.getContext().typesAreCompatible( + STy.getUnqualifiedType(), Ty.getUnqualifiedType()) + && "Implicit cast types must be compatible"); + + Visit(E->getSubExpr()); +} + +void AggExprEmitter::VisitCallExpr(const CallExpr *E) +{ + RValue RV = CGF.EmitCallExpr(E); + assert(RV.isAggregate() && "Return value must be aggregate value!"); + + // If the result is ignored, don't copy from the value. + if (DestPtr == 0) + // FIXME: If the source is volatile, we must read from it. + return; + + EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType()); +} + +void AggExprEmitter::VisitOverloadExpr(const OverloadExpr *E) +{ + RValue RV = CGF.EmitCallExpr(E->getFn(), E->arg_begin(), + E->getNumArgs(CGF.getContext())); + assert(RV.isAggregate() && "Return value must be aggregate value!"); + + // If the result is ignored, don't copy from the value. + if (DestPtr == 0) + // FIXME: If the source is volatile, we must read from it. + return; + + EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType()); +} + +void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { + CGF.EmitCompoundStmt(*E->getSubStmt(), true, DestPtr, VolatileDest); +} + +void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { + CGF.WarnUnsupported(E, "aggregate binary expression"); +} + +void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { + // For an assignment to work, the value on the right has + // to be compatible with the value on the left. + assert(CGF.getContext().typesAreCompatible( + E->getLHS()->getType().getUnqualifiedType(), + E->getRHS()->getType().getUnqualifiedType()) + && "Invalid assignment"); + LValue LHS = CGF.EmitLValue(E->getLHS()); + + // Codegen the RHS so that it stores directly into the LHS. + CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/); + + if (DestPtr == 0) + return; + + // If the result of the assignment is used, copy the RHS there also. + EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType()); +} + +void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) { + llvm::BasicBlock *LHSBlock = new llvm::BasicBlock("cond.?"); + llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:"); + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont"); + + llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond()); + Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + + CGF.EmitBlock(LHSBlock); + + // Handle the GNU extension for missing LHS. + assert(E->getLHS() && "Must have LHS for aggregate value"); + + Visit(E->getLHS()); + Builder.CreateBr(ContBlock); + LHSBlock = Builder.GetInsertBlock(); + + CGF.EmitBlock(RHSBlock); + + Visit(E->getRHS()); + Builder.CreateBr(ContBlock); + RHSBlock = Builder.GetInsertBlock(); + + CGF.EmitBlock(ContBlock); +} + +void AggExprEmitter::EmitNonConstInit(InitListExpr *E) { + + const llvm::PointerType *APType = + cast<llvm::PointerType>(DestPtr->getType()); + const llvm::Type *DestType = APType->getElementType(); + + if (const llvm::ArrayType *AType = dyn_cast<llvm::ArrayType>(DestType)) { + unsigned NumInitElements = E->getNumInits(); + + llvm::Value *Idxs[] = { + llvm::Constant::getNullValue(llvm::Type::Int32Ty), + NULL + }; + llvm::Value *NextVal = NULL; + unsigned i; + for (i = 0; i != NumInitElements; ++i) { + Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2,".array"); + Expr *Init = E->getInit(i); + if (isa<InitListExpr>(Init)) + CGF.EmitAggExpr(Init, NextVal, VolatileDest); + else + Builder.CreateStore(CGF.EmitScalarExpr(Init), NextVal); + } + + // Emit remaining default initializers + unsigned NumArrayElements = AType->getNumElements(); + QualType QType = E->getInit(0)->getType(); + const llvm::Type *EType = AType->getElementType(); + for (/*Do not initialize i*/; i < NumArrayElements; ++i) { + Idxs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + NextVal = Builder.CreateGEP(DestPtr, Idxs, Idxs + 2,".array"); + if (EType->isFirstClassType()) + Builder.CreateStore(llvm::Constant::getNullValue(EType), NextVal); + else + EmitAggregateClear(NextVal, QType); + } + } else + assert(false && "Invalid initializer"); +} + +void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { + + if (E->isConstantExpr(CGF.CGM.getContext(), NULL)) { + llvm::Constant *V = CGF.CGM.EmitConstantExpr(E); + // Create global value to hold this array. + V = new llvm::GlobalVariable(V->getType(), true, + llvm::GlobalValue::InternalLinkage, + V, ".array", + &CGF.CGM.getModule()); + + EmitAggregateCopy(DestPtr, V , E->getType()); + return; + } else { + if (!E->getType()->isArrayType()) { + CGF.WarnUnsupported(E, "aggregate init-list expression"); + return; + } + EmitNonConstInit(E); + } +} + +//===----------------------------------------------------------------------===// +// Entry Points into this File +//===----------------------------------------------------------------------===// + +/// EmitAggExpr - Emit the computation of the specified expression of +/// aggregate type. The result is computed into DestPtr. Note that if +/// DestPtr is null, the value of the aggregate expression is not needed. +void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, + bool VolatileDest) { + assert(E && hasAggregateLLVMType(E->getType()) && + "Invalid aggregate expression to emit"); + + AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast<Expr*>(E)); +} diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp new file mode 100644 index 00000000000..b1de93570d9 --- /dev/null +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -0,0 +1,542 @@ +//===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Expr nodes with complex types as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Compiler.h" +using namespace clang; +using namespace CodeGen; + +//===----------------------------------------------------------------------===// +// Complex Expression Emitter +//===----------------------------------------------------------------------===// + +typedef CodeGenFunction::ComplexPairTy ComplexPairTy; + +namespace { +class VISIBILITY_HIDDEN ComplexExprEmitter + : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> { + CodeGenFunction &CGF; + llvm::LLVMFoldingBuilder &Builder; +public: + ComplexExprEmitter(CodeGenFunction &cgf) : CGF(cgf), Builder(CGF.Builder) { + } + + + //===--------------------------------------------------------------------===// + // Utilities + //===--------------------------------------------------------------------===// + + /// EmitLoadOfLValue - Given an expression with complex type that represents a + /// value l-value, this method emits the address of the l-value, then loads + /// and returns the result. + ComplexPairTy EmitLoadOfLValue(const Expr *E) { + LValue LV = CGF.EmitLValue(E); + // FIXME: Volatile + return EmitLoadOfComplex(LV.getAddress(), false); + } + + /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load + /// the real and imaginary pieces. + ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile); + + /// EmitStoreOfComplex - Store the specified real/imag parts into the + /// specified value pointer. + void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol); + + /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType. + ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType, + QualType DestType); + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + ComplexPairTy VisitStmt(Stmt *S) { + S->dump(CGF.getContext().getSourceManager()); + assert(0 && "Stmt can't have complex result type!"); + return ComplexPairTy(); + } + ComplexPairTy VisitExpr(Expr *S); + ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());} + ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL); + + // l-values. + ComplexPairTy VisitDeclRefExpr(const Expr *E) { return EmitLoadOfLValue(E); } + ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); } + ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); } + + // FIXME: CompoundLiteralExpr + + ComplexPairTy EmitCast(Expr *Op, QualType DestTy); + ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) { + // Unlike for scalars, we don't have to worry about function->ptr demotion + // here. + return EmitCast(E->getSubExpr(), E->getType()); + } + ComplexPairTy VisitCastExpr(CastExpr *E) { + return EmitCast(E->getSubExpr(), E->getType()); + } + ComplexPairTy VisitCallExpr(const CallExpr *E); + ComplexPairTy VisitStmtExpr(const StmtExpr *E); + ComplexPairTy VisitOverloadExpr(const OverloadExpr *OE); + + // Operators. + ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E, + bool isInc, bool isPre); + ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) { + return VisitPrePostIncDec(E, false, false); + } + ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) { + return VisitPrePostIncDec(E, true, false); + } + ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) { + return VisitPrePostIncDec(E, false, true); + } + ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) { + return VisitPrePostIncDec(E, true, true); + } + ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); } + ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + ComplexPairTy VisitUnaryMinus (const UnaryOperator *E); + ComplexPairTy VisitUnaryNot (const UnaryOperator *E); + // LNot,SizeOf,AlignOf,Real,Imag never return complex. + ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + + struct BinOpInfo { + ComplexPairTy LHS; + ComplexPairTy RHS; + QualType Ty; // Computation Type. + }; + + BinOpInfo EmitBinOps(const BinaryOperator *E); + ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func) + (const BinOpInfo &)); + + ComplexPairTy EmitBinAdd(const BinOpInfo &Op); + ComplexPairTy EmitBinSub(const BinOpInfo &Op); + ComplexPairTy EmitBinMul(const BinOpInfo &Op); + ComplexPairTy EmitBinDiv(const BinOpInfo &Op); + + ComplexPairTy VisitBinMul(const BinaryOperator *E) { + return EmitBinMul(EmitBinOps(E)); + } + ComplexPairTy VisitBinAdd(const BinaryOperator *E) { + return EmitBinAdd(EmitBinOps(E)); + } + ComplexPairTy VisitBinSub(const BinaryOperator *E) { + return EmitBinSub(EmitBinOps(E)); + } + ComplexPairTy VisitBinDiv(const BinaryOperator *E) { + return EmitBinDiv(EmitBinOps(E)); + } + + // Compound assignments. + ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) { + return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd); + } + ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) { + return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub); + } + ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) { + return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul); + } + ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) { + return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv); + } + + // GCC rejects rem/and/or/xor for integer complex. + // Logical and/or always return int, never complex. + + // No comparisons produce a complex result. + ComplexPairTy VisitBinAssign (const BinaryOperator *E); + ComplexPairTy VisitBinComma (const BinaryOperator *E); + + + ComplexPairTy VisitConditionalOperator(const ConditionalOperator *CO); + ComplexPairTy VisitChooseExpr(ChooseExpr *CE); +}; +} // end anonymous namespace. + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +/// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to +/// load the real and imaginary pieces, returning them as Real/Imag. +ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr, + bool isVolatile) { + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); + + llvm::SmallString<64> Name(SrcPtr->getNameStart(), + SrcPtr->getNameStart()+SrcPtr->getNameLen()); + + Name += ".realp"; + llvm::Value *Ops[] = {Zero, Zero}; + llvm::Value *RealPtr = Builder.CreateGEP(SrcPtr, Ops, Ops+2, Name.c_str()); + + Name.pop_back(); // .realp -> .real + llvm::Value *Real = Builder.CreateLoad(RealPtr, isVolatile, Name.c_str()); + + Name.resize(Name.size()-4); // .real -> .imagp + Name += "imagp"; + + Ops[1] = One; // { Ops = { Zero, One } + llvm::Value *ImagPtr = Builder.CreateGEP(SrcPtr, Ops, Ops+2, Name.c_str()); + + Name.pop_back(); // .imagp -> .imag + llvm::Value *Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.c_str()); + return ComplexPairTy(Real, Imag); +} + +/// EmitStoreOfComplex - Store the specified real/imag parts into the +/// specified value pointer. +void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *Ptr, + bool isVolatile) { + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); + + llvm::Value *Ops[] = {Zero, Zero}; + llvm::Value *RealPtr = Builder.CreateGEP(Ptr, Ops, Ops+2, "real"); + + Ops[1] = One; // { Ops = { Zero, One } + llvm::Value *ImagPtr = Builder.CreateGEP(Ptr, Ops, Ops+2, "imag"); + + Builder.CreateStore(Val.first, RealPtr, isVolatile); + Builder.CreateStore(Val.second, ImagPtr, isVolatile); +} + + + +//===----------------------------------------------------------------------===// +// Visitor Methods +//===----------------------------------------------------------------------===// + +ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { + CGF.WarnUnsupported(E, "complex expression"); + const llvm::Type *EltTy = + CGF.ConvertType(E->getType()->getAsComplexType()->getElementType()); + llvm::Value *U = llvm::UndefValue::get(EltTy); + return ComplexPairTy(U, U); +} + +ComplexPairTy ComplexExprEmitter:: +VisitImaginaryLiteral(const ImaginaryLiteral *IL) { + llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr()); + return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); +} + + +ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { + return CGF.EmitCallExpr(E).getComplexVal(); +} + +ComplexPairTy ComplexExprEmitter::VisitOverloadExpr(const OverloadExpr *E) { + return CGF.EmitCallExpr(E->getFn(), E->arg_begin(), + E->getNumArgs(CGF.getContext())).getComplexVal(); +} + +ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) { + return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal(); +} + +/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType. +ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val, + QualType SrcType, + QualType DestType) { + // Get the src/dest element type. + SrcType = cast<ComplexType>(SrcType.getCanonicalType())->getElementType(); + DestType = cast<ComplexType>(DestType.getCanonicalType())->getElementType(); + + // C99 6.3.1.6: When a value of complextype is converted to another + // complex type, both the real and imaginary parts followthe conversion + // rules for the corresponding real types. + Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType); + Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType); + return Val; +} + +ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) { + // Two cases here: cast from (complex to complex) and (scalar to complex). + if (Op->getType()->isComplexType()) + return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy); + + // C99 6.3.1.7: When a value of real type is converted to a complex type, the + // real part of the complex result value is determined by the rules of + // conversion to the corresponding real type and the imaginary part of the + // complex result value is a positive zero or an unsigned zero. + llvm::Value *Elt = CGF.EmitScalarExpr(Op); + + // Convert the input element to the element type of the complex. + DestTy = cast<ComplexType>(DestTy.getCanonicalType())->getElementType(); + Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy); + + // Return (realval, 0). + return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType())); +} + +ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, + bool isInc, bool isPre) { + LValue LV = CGF.EmitLValue(E->getSubExpr()); + // FIXME: Handle volatile! + ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(), false); + + uint64_t AmountVal = isInc ? 1 : -1; + + llvm::Value *NextVal; + if (isa<llvm::IntegerType>(InVal.first->getType())) + NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal); + else if (InVal.first->getType() == llvm::Type::FloatTy) + // FIXME: Handle long double. + NextVal = + llvm::ConstantFP::get(InVal.first->getType(), + llvm::APFloat(static_cast<float>(AmountVal))); + else { + // FIXME: Handle long double. + assert(InVal.first->getType() == llvm::Type::DoubleTy); + NextVal = + llvm::ConstantFP::get(InVal.first->getType(), + llvm::APFloat(static_cast<double>(AmountVal))); + } + + // Add the inc/dec to the real part. + NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); + + ComplexPairTy IncVal(NextVal, InVal.second); + + // Store the updated result through the lvalue. + EmitStoreOfComplex(IncVal, LV.getAddress(), false); /* FIXME: Volatile */ + + // If this is a postinc, return the value read from memory, otherwise use the + // updated value. + return isPre ? IncVal : InVal; +} + +ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { + ComplexPairTy Op = Visit(E->getSubExpr()); + llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r"); + llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i"); + return ComplexPairTy(ResR, ResI); +} + +ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) { + // ~(a+ib) = a + i*-b + ComplexPairTy Op = Visit(E->getSubExpr()); + llvm::Value *ResI = Builder.CreateNeg(Op.second, "conj.i"); + return ComplexPairTy(Op.first, ResI); +} + +ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) { + llvm::Value *ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r"); + llvm::Value *ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i"); + return ComplexPairTy(ResR, ResI); +} + +ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) { + llvm::Value *ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r"); + llvm::Value *ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i"); + return ComplexPairTy(ResR, ResI); +} + + +ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { + llvm::Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl"); + llvm::Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr"); + llvm::Value *ResR = Builder.CreateSub(ResRl, ResRr, "mul.r"); + + llvm::Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il"); + llvm::Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir"); + llvm::Value *ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i"); + return ComplexPairTy(ResR, ResI); +} + +ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { + llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second; + llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second; + + // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) + llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c + llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d + llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd + + llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c + llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d + llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd + + llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c + llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d + llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad + + llvm::Value *DSTr, *DSTi; + if (Tmp3->getType()->isFloatingPoint()) { + DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp"); + DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp"); + } else { + if (Op.Ty->getAsComplexType()->getElementType()->isUnsignedIntegerType()) { + DSTr = Builder.CreateUDiv(Tmp3, Tmp6, "tmp"); + DSTi = Builder.CreateUDiv(Tmp9, Tmp6, "tmp"); + } else { + DSTr = Builder.CreateSDiv(Tmp3, Tmp6, "tmp"); + DSTi = Builder.CreateSDiv(Tmp9, Tmp6, "tmp"); + } + } + + return ComplexPairTy(DSTr, DSTi); +} + +ComplexExprEmitter::BinOpInfo +ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) { + BinOpInfo Ops; + Ops.LHS = Visit(E->getLHS()); + Ops.RHS = Visit(E->getRHS()); + Ops.Ty = E->getType(); + return Ops; +} + + +// Compound assignments. +ComplexPairTy ComplexExprEmitter:: +EmitCompoundAssign(const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ + QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType(); + + // Load the LHS and RHS operands. + LValue LHSLV = CGF.EmitLValue(E->getLHS()); + + BinOpInfo OpInfo; + OpInfo.Ty = E->getComputationType(); + + // We know the LHS is a complex lvalue. + OpInfo.LHS = EmitLoadOfComplex(LHSLV.getAddress(), false);// FIXME: Volatile. + OpInfo.LHS = EmitComplexToComplexCast(OpInfo.LHS, LHSTy, OpInfo.Ty); + + // It is possible for the RHS to be complex or scalar. + OpInfo.RHS = EmitCast(E->getRHS(), OpInfo.Ty); + + // Expand the binary operator. + ComplexPairTy Result = (this->*Func)(OpInfo); + + // Truncate the result back to the LHS type. + Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy); + + // Store the result value into the LHS lvalue. + EmitStoreOfComplex(Result, LHSLV.getAddress(), false); // FIXME: VOLATILE + return Result; +} + +ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { + assert(E->getLHS()->getType().getCanonicalType() == + E->getRHS()->getType().getCanonicalType() && "Invalid assignment"); + // Emit the RHS. + ComplexPairTy Val = Visit(E->getRHS()); + + // Compute the address to store into. + LValue LHS = CGF.EmitLValue(E->getLHS()); + + // Store into it. + // FIXME: Volatility! + EmitStoreOfComplex(Val, LHS.getAddress(), false); + return Val; +} + +ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { + CGF.EmitStmt(E->getLHS()); + return Visit(E->getRHS()); +} + +ComplexPairTy ComplexExprEmitter:: +VisitConditionalOperator(const ConditionalOperator *E) { + llvm::BasicBlock *LHSBlock = new llvm::BasicBlock("cond.?"); + llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:"); + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont"); + + llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond()); + Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + + CGF.EmitBlock(LHSBlock); + + // Handle the GNU extension for missing LHS. + assert(E->getLHS() && "Must have LHS for complex value"); + + ComplexPairTy LHS = Visit(E->getLHS()); + Builder.CreateBr(ContBlock); + LHSBlock = Builder.GetInsertBlock(); + + CGF.EmitBlock(RHSBlock); + + ComplexPairTy RHS = Visit(E->getRHS()); + Builder.CreateBr(ContBlock); + RHSBlock = Builder.GetInsertBlock(); + + CGF.EmitBlock(ContBlock); + + // Create a PHI node for the real part. + llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), "cond.r"); + RealPN->reserveOperandSpace(2); + RealPN->addIncoming(LHS.first, LHSBlock); + RealPN->addIncoming(RHS.first, RHSBlock); + + // Create a PHI node for the imaginary part. + llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), "cond.i"); + ImagPN->reserveOperandSpace(2); + ImagPN->addIncoming(LHS.second, LHSBlock); + ImagPN->addIncoming(RHS.second, RHSBlock); + + return ComplexPairTy(RealPN, ImagPN); +} + +ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) { + // Emit the LHS or RHS as appropriate. + return Visit(E->isConditionTrue(CGF.getContext()) ? E->getLHS() :E->getRHS()); +} + +//===----------------------------------------------------------------------===// +// Entry Point into this File +//===----------------------------------------------------------------------===// + +/// EmitComplexExpr - Emit the computation of the specified expression of +/// complex type, ignoring the result. +ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E) { + assert(E && E->getType()->isComplexType() && + "Invalid complex expression to emit"); + + return ComplexExprEmitter(*this).Visit(const_cast<Expr*>(E)); +} + +/// EmitComplexExprIntoAddr - Emit the computation of the specified expression +/// of complex type, storing into the specified Value*. +void CodeGenFunction::EmitComplexExprIntoAddr(const Expr *E, + llvm::Value *DestAddr, + bool DestIsVolatile) { + assert(E && E->getType()->isComplexType() && + "Invalid complex expression to emit"); + ComplexExprEmitter Emitter(*this); + ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E)); + Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile); +} + +/// LoadComplexFromAddr - Load a complex number from the specified address. +ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr, + bool SrcIsVolatile) { + return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile); +} diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp new file mode 100644 index 00000000000..e2405b88f37 --- /dev/null +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -0,0 +1,627 @@ +//===--- CGExprConstant.cpp - Emit LLVM Code from Constant Expressions ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Constant Expr nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Support/Compiler.h" +using namespace clang; +using namespace CodeGen; + +namespace { +class VISIBILITY_HIDDEN ConstExprEmitter : + public StmtVisitor<ConstExprEmitter, llvm::Constant*> { + CodeGenModule &CGM; + CodeGenFunction *CGF; +public: + ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf) + : CGM(cgm), CGF(cgf) { + } + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + llvm::Constant *VisitStmt(Stmt *S) { + CGM.WarnUnsupported(S, "constant expression"); + QualType T = cast<Expr>(S)->getType(); + return llvm::UndefValue::get(CGM.getTypes().ConvertType(T)); + } + + llvm::Constant *VisitParenExpr(ParenExpr *PE) { + return Visit(PE->getSubExpr()); + } + + // Leaves + llvm::Constant *VisitIntegerLiteral(const IntegerLiteral *E) { + return llvm::ConstantInt::get(E->getValue()); + } + llvm::Constant *VisitFloatingLiteral(const FloatingLiteral *E) { + return llvm::ConstantFP::get(ConvertType(E->getType()), E->getValue()); + } + llvm::Constant *VisitCharacterLiteral(const CharacterLiteral *E) { + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); + } + llvm::Constant *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); + } + + llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + return Visit(E->getInitializer()); + } + + llvm::Constant *VisitCastExpr(const CastExpr* E) { + llvm::Constant *C = Visit(E->getSubExpr()); + + return EmitConversion(C, E->getSubExpr()->getType(), E->getType()); + } + + llvm::Constant *EmitArrayInitialization(InitListExpr *ILE, + const llvm::ArrayType *AType) { + std::vector<llvm::Constant*> Elts; + unsigned NumInitElements = ILE->getNumInits(); + // FIXME: Check for wide strings + if (NumInitElements > 0 && isa<StringLiteral>(ILE->getInit(0)) && + ILE->getType()->getAsArrayType()->getElementType()->isCharType()) + return Visit(ILE->getInit(0)); + const llvm::Type *ElemTy = AType->getElementType(); + unsigned NumElements = AType->getNumElements(); + + // Initialising an array requires us to automatically + // initialise any elements that have not been initialised explicitly + unsigned NumInitableElts = std::min(NumInitElements, NumElements); + + // Copy initializer elements. + unsigned i = 0; + for (; i < NumInitableElts; ++i) { + + llvm::Constant *C = Visit(ILE->getInit(i)); + // FIXME: Remove this when sema of initializers is finished (and the code + // above). + if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) { + if (ILE->getType()->isVoidType()) return 0; + return llvm::UndefValue::get(AType); + } + assert (C && "Failed to create initializer expression"); + Elts.push_back(C); + } + + // Initialize remaining array elements. + for (; i < NumElements; ++i) + Elts.push_back(llvm::Constant::getNullValue(ElemTy)); + + return llvm::ConstantArray::get(AType, Elts); + } + + llvm::Constant *EmitStructInitialization(InitListExpr *ILE, + const llvm::StructType *SType) { + + TagDecl *TD = ILE->getType()->getAsRecordType()->getDecl(); + std::vector<llvm::Constant*> Elts; + const CGRecordLayout *CGR = CGM.getTypes().getCGRecordLayout(TD); + unsigned NumInitElements = ILE->getNumInits(); + unsigned NumElements = SType->getNumElements(); + + // Initialising an structure requires us to automatically + // initialise any elements that have not been initialised explicitly + unsigned NumInitableElts = std::min(NumInitElements, NumElements); + + // Copy initializer elements. Skip padding fields. + unsigned EltNo = 0; // Element no in ILE + unsigned FieldNo = 0; // Field no in SType + while (EltNo < NumInitableElts) { + + // Zero initialize padding field. + if (CGR->isPaddingField(FieldNo)) { + const llvm::Type *FieldTy = SType->getElementType(FieldNo); + Elts.push_back(llvm::Constant::getNullValue(FieldTy)); + FieldNo++; + continue; + } + + llvm::Constant *C = Visit(ILE->getInit(EltNo)); + // FIXME: Remove this when sema of initializers is finished (and the code + // above). + if (C == 0 && ILE->getInit(EltNo)->getType()->isVoidType()) { + if (ILE->getType()->isVoidType()) return 0; + return llvm::UndefValue::get(SType); + } + assert (C && "Failed to create initializer expression"); + Elts.push_back(C); + EltNo++; + FieldNo++; + } + + // Initialize remaining structure elements. + for (unsigned i = Elts.size(); i < NumElements; ++i) { + const llvm::Type *FieldTy = SType->getElementType(i); + Elts.push_back(llvm::Constant::getNullValue(FieldTy)); + } + + return llvm::ConstantStruct::get(SType, Elts); + } + + llvm::Constant *EmitVectorInitialization(InitListExpr *ILE, + const llvm::VectorType *VType) { + + std::vector<llvm::Constant*> Elts; + unsigned NumInitElements = ILE->getNumInits(); + unsigned NumElements = VType->getNumElements(); + + assert (NumInitElements == NumElements + && "Unsufficient vector init elelments"); + // Copy initializer elements. + unsigned i = 0; + for (; i < NumElements; ++i) { + + llvm::Constant *C = Visit(ILE->getInit(i)); + // FIXME: Remove this when sema of initializers is finished (and the code + // above). + if (C == 0 && ILE->getInit(i)->getType()->isVoidType()) { + if (ILE->getType()->isVoidType()) return 0; + return llvm::UndefValue::get(VType); + } + assert (C && "Failed to create initializer expression"); + Elts.push_back(C); + } + + return llvm::ConstantVector::get(VType, Elts); + } + + llvm::Constant *VisitInitListExpr(InitListExpr *ILE) { + const llvm::CompositeType *CType = + dyn_cast<llvm::CompositeType>(ConvertType(ILE->getType())); + + if (!CType) { + // We have a scalar in braces. Just use the first element. + return Visit(ILE->getInit(0)); + } + + if (const llvm::ArrayType *AType = dyn_cast<llvm::ArrayType>(CType)) + return EmitArrayInitialization(ILE, AType); + + if (const llvm::StructType *SType = dyn_cast<llvm::StructType>(CType)) + return EmitStructInitialization(ILE, SType); + + if (const llvm::VectorType *VType = dyn_cast<llvm::VectorType>(CType)) + return EmitVectorInitialization(ILE, VType); + + // Make sure we have an array at this point + assert(0 && "Unable to handle InitListExpr"); + // Get rid of control reaches end of void function warning. + // Not reached. + return 0; + } + + llvm::Constant *VisitImplicitCastExpr(ImplicitCastExpr *ICExpr) { + Expr* SExpr = ICExpr->getSubExpr(); + QualType SType = SExpr->getType(); + llvm::Constant *C; // the intermediate expression + QualType T; // the type of the intermediate expression + if (SType->isArrayType()) { + // Arrays decay to a pointer to the first element + // VLAs would require special handling, but they can't occur here + C = EmitLValue(SExpr); + llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Ops[] = {Idx0, Idx0}; + C = llvm::ConstantExpr::getGetElementPtr(C, Ops, 2); + + QualType ElemType = SType->getAsArrayType()->getElementType(); + T = CGM.getContext().getPointerType(ElemType); + } else if (SType->isFunctionType()) { + // Function types decay to a pointer to the function + C = EmitLValue(SExpr); + T = CGM.getContext().getPointerType(SType); + } else { + C = Visit(SExpr); + T = SType; + } + + // Perform the conversion; note that an implicit cast can both promote + // and convert an array/function + return EmitConversion(C, T, ICExpr->getType()); + } + + llvm::Constant *VisitStringLiteral(StringLiteral *E) { + const char *StrData = E->getStrData(); + unsigned Len = E->getByteLength(); + assert(!E->getType()->isPointerType() && "Strings are always arrays"); + + // Otherwise this must be a string initializing an array in a static + // initializer. Don't emit it as the address of the string, emit the string + // data itself as an inline array. + const ConstantArrayType *CAT = E->getType()->getAsConstantArrayType(); + assert(CAT && "String isn't pointer or array!"); + + std::string Str(StrData, StrData + Len); + // Null terminate the string before potentially truncating it. + // FIXME: What about wchar_t strings? + Str.push_back(0); + + uint64_t RealLen = CAT->getSize().getZExtValue(); + // String or grow the initializer to the required size. + if (RealLen != Str.size()) + Str.resize(RealLen); + + return llvm::ConstantArray::get(Str, false); + } + + llvm::Constant *VisitDeclRefExpr(DeclRefExpr *E) { + const ValueDecl *Decl = E->getDecl(); + if (const EnumConstantDecl *EC = dyn_cast<EnumConstantDecl>(Decl)) + return llvm::ConstantInt::get(EC->getInitVal()); + assert(0 && "Unsupported decl ref type!"); + return 0; + } + + llvm::Constant *VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) { + return EmitSizeAlignOf(E->getArgumentType(), E->getType(), E->isSizeOf()); + } + + // Unary operators + llvm::Constant *VisitUnaryPlus(const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + llvm::Constant *VisitUnaryMinus(const UnaryOperator *E) { + return llvm::ConstantExpr::getNeg(Visit(E->getSubExpr())); + } + llvm::Constant *VisitUnaryNot(const UnaryOperator *E) { + return llvm::ConstantExpr::getNot(Visit(E->getSubExpr())); + } + llvm::Constant *VisitUnaryLNot(const UnaryOperator *E) { + llvm::Constant *SubExpr = Visit(E->getSubExpr()); + + if (E->getSubExpr()->getType()->isRealFloatingType()) { + // Compare against 0.0 for fp scalars. + llvm::Constant *Zero = llvm::Constant::getNullValue(SubExpr->getType()); + SubExpr = llvm::ConstantExpr::getFCmp(llvm::FCmpInst::FCMP_UEQ, SubExpr, + Zero); + } else { + assert((E->getSubExpr()->getType()->isIntegerType() || + E->getSubExpr()->getType()->isPointerType()) && + "Unknown scalar type to convert"); + // Compare against an integer or pointer null. + llvm::Constant *Zero = llvm::Constant::getNullValue(SubExpr->getType()); + SubExpr = llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, SubExpr, + Zero); + } + + return llvm::ConstantExpr::getZExt(SubExpr, ConvertType(E->getType())); + } + llvm::Constant *VisitUnarySizeOf(const UnaryOperator *E) { + return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), true); + } + llvm::Constant *VisitUnaryAlignOf(const UnaryOperator *E) { + return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), false); + } + llvm::Constant *VisitUnaryAddrOf(const UnaryOperator *E) { + return EmitLValue(E->getSubExpr()); + } + llvm::Constant *VisitUnaryOffsetOf(const UnaryOperator *E) { + int64_t Val = E->evaluateOffsetOf(CGM.getContext()); + + assert(E->getType()->isIntegerType() && "Result type must be an integer!"); + + uint32_t ResultWidth = + static_cast<uint32_t>(CGM.getContext().getTypeSize(E->getType())); + return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val)); + } + + // Binary operators + llvm::Constant *VisitBinOr(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + return llvm::ConstantExpr::getOr(LHS, RHS); + } + llvm::Constant *VisitBinSub(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + if (!isa<llvm::PointerType>(RHS->getType())) { + // pointer - int + if (isa<llvm::PointerType>(LHS->getType())) { + llvm::Constant *Idx = llvm::ConstantExpr::getNeg(RHS); + + return llvm::ConstantExpr::getGetElementPtr(LHS, &Idx, 1); + } + + // int - int + return llvm::ConstantExpr::getSub(LHS, RHS); + } + + assert(0 && "Unhandled bin sub case!"); + return 0; + } + + llvm::Constant *VisitBinShl(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + // LLVM requires the LHS and RHS to be the same type: promote or truncate the + // RHS to the same size as the LHS. + if (LHS->getType() != RHS->getType()) + RHS = llvm::ConstantExpr::getIntegerCast(RHS, LHS->getType(), false); + + return llvm::ConstantExpr::getShl(LHS, RHS); + } + + llvm::Constant *VisitBinMul(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + return llvm::ConstantExpr::getMul(LHS, RHS); + } + + llvm::Constant *VisitBinDiv(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + if (LHS->getType()->isFPOrFPVector()) + return llvm::ConstantExpr::getFDiv(LHS, RHS); + else if (E->getType()->isUnsignedIntegerType()) + return llvm::ConstantExpr::getUDiv(LHS, RHS); + else + return llvm::ConstantExpr::getSDiv(LHS, RHS); + } + + llvm::Constant *VisitBinAdd(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + if (!E->getType()->isPointerType()) + return llvm::ConstantExpr::getAdd(LHS, RHS); + + llvm::Constant *Ptr, *Idx; + if (isa<llvm::PointerType>(LHS->getType())) { // pointer + int + Ptr = LHS; + Idx = RHS; + } else { // int + pointer + Ptr = RHS; + Idx = LHS; + } + + return llvm::ConstantExpr::getGetElementPtr(Ptr, &Idx, 1); + } + + llvm::Constant *VisitBinAnd(const BinaryOperator *E) { + llvm::Constant *LHS = Visit(E->getLHS()); + llvm::Constant *RHS = Visit(E->getRHS()); + + return llvm::ConstantExpr::getAnd(LHS, RHS); + } + + // Utility methods + const llvm::Type *ConvertType(QualType T) { + return CGM.getTypes().ConvertType(T); + } + + llvm::Constant *EmitConversionToBool(llvm::Constant *Src, QualType SrcType) { + assert(SrcType->isCanonical() && "EmitConversion strips typedefs"); + + if (SrcType->isRealFloatingType()) { + // Compare against 0.0 for fp scalars. + llvm::Constant *Zero = llvm::Constant::getNullValue(Src->getType()); + return llvm::ConstantExpr::getFCmp(llvm::FCmpInst::FCMP_UNE, Src, Zero); + } + + assert((SrcType->isIntegerType() || SrcType->isPointerType()) && + "Unknown scalar type to convert"); + + // Compare against an integer or pointer null. + llvm::Constant *Zero = llvm::Constant::getNullValue(Src->getType()); + return llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_NE, Src, Zero); + } + + llvm::Constant *EmitConversion(llvm::Constant *Src, QualType SrcType, + QualType DstType) { + SrcType = SrcType.getCanonicalType(); + DstType = DstType.getCanonicalType(); + if (SrcType == DstType) return Src; + + // Handle conversions to bool first, they are special: comparisons against 0. + if (DstType->isBooleanType()) + return EmitConversionToBool(Src, SrcType); + + const llvm::Type *DstTy = ConvertType(DstType); + + // Ignore conversions like int -> uint. + if (Src->getType() == DstTy) + return Src; + + // Handle pointer conversions next: pointers can only be converted to/from + // other pointers and integers. + if (isa<PointerType>(DstType)) { + // The source value may be an integer, or a pointer. + if (isa<llvm::PointerType>(Src->getType())) + return llvm::ConstantExpr::getBitCast(Src, DstTy); + assert(SrcType->isIntegerType() &&"Not ptr->ptr or int->ptr conversion?"); + return llvm::ConstantExpr::getIntToPtr(Src, DstTy); + } + + if (isa<PointerType>(SrcType)) { + // Must be an ptr to int cast. + assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?"); + return llvm::ConstantExpr::getPtrToInt(Src, DstTy); + } + + // A scalar source can be splatted to a vector of the same element type + if (isa<llvm::VectorType>(DstTy) && !isa<VectorType>(SrcType)) { + const llvm::VectorType *VT = cast<llvm::VectorType>(DstTy); + assert((VT->getElementType() == Src->getType()) && + "Vector element type must match scalar type to splat."); + unsigned NumElements = DstType->getAsVectorType()->getNumElements(); + llvm::SmallVector<llvm::Constant*, 16> Elements; + for (unsigned i = 0; i < NumElements; i++) + Elements.push_back(Src); + + return llvm::ConstantVector::get(&Elements[0], NumElements); + } + + if (isa<llvm::VectorType>(Src->getType()) || + isa<llvm::VectorType>(DstTy)) { + return llvm::ConstantExpr::getBitCast(Src, DstTy); + } + + // Finally, we have the arithmetic types: real int/float. + if (isa<llvm::IntegerType>(Src->getType())) { + bool InputSigned = SrcType->isSignedIntegerType(); + if (isa<llvm::IntegerType>(DstTy)) + return llvm::ConstantExpr::getIntegerCast(Src, DstTy, InputSigned); + else if (InputSigned) + return llvm::ConstantExpr::getSIToFP(Src, DstTy); + else + return llvm::ConstantExpr::getUIToFP(Src, DstTy); + } + + assert(Src->getType()->isFloatingPoint() && "Unknown real conversion"); + if (isa<llvm::IntegerType>(DstTy)) { + if (DstType->isSignedIntegerType()) + return llvm::ConstantExpr::getFPToSI(Src, DstTy); + else + return llvm::ConstantExpr::getFPToUI(Src, DstTy); + } + + assert(DstTy->isFloatingPoint() && "Unknown real conversion"); + if (DstTy->getTypeID() < Src->getType()->getTypeID()) + return llvm::ConstantExpr::getFPTrunc(Src, DstTy); + else + return llvm::ConstantExpr::getFPExtend(Src, DstTy); + } + + llvm::Constant *EmitSizeAlignOf(QualType TypeToSize, + QualType RetType, bool isSizeOf) { + std::pair<uint64_t, unsigned> Info = + CGM.getContext().getTypeInfo(TypeToSize); + + uint64_t Val = isSizeOf ? Info.first : Info.second; + Val /= 8; // Return size in bytes, not bits. + + assert(RetType->isIntegerType() && "Result type must be an integer!"); + + uint32_t ResultWidth = + static_cast<uint32_t>(CGM.getContext().getTypeSize(RetType)); + return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val)); + } + + llvm::Constant *EmitLValue(Expr *E) { + switch (E->getStmtClass()) { + default: break; + case Expr::ParenExprClass: + // Elide parenthesis + return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); + case Expr::CompoundLiteralExprClass: { + // Note that due to the nature of compound literals, this is guaranteed + // to be the only use of the variable, so we just generate it here. + CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E); + llvm::Constant* C = Visit(CLE->getInitializer()); + C = new llvm::GlobalVariable(C->getType(),E->getType().isConstQualified(), + llvm::GlobalValue::InternalLinkage, + C, ".compoundliteral", &CGM.getModule()); + return C; + } + case Expr::DeclRefExprClass: { + ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) + return CGM.GetAddrOfFunctionDecl(FD, false); + if (const FileVarDecl* VD = dyn_cast<FileVarDecl>(Decl)) + return CGM.GetAddrOfGlobalVar(VD, false); + if (const BlockVarDecl* BVD = dyn_cast<BlockVarDecl>(Decl)) { + assert(CGF && "Can't access static local vars without CGF"); + return CGF->GetAddrOfStaticLocalVar(BVD); + } + break; + } + case Expr::MemberExprClass: { + MemberExpr* ME = cast<MemberExpr>(E); + llvm::Constant *Base; + if (ME->isArrow()) + Base = Visit(ME->getBase()); + else + Base = EmitLValue(ME->getBase()); + + unsigned FieldNumber = CGM.getTypes().getLLVMFieldNo(ME->getMemberDecl()); + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, + FieldNumber); + llvm::Value *Ops[] = {Zero, Idx}; + return llvm::ConstantExpr::getGetElementPtr(Base, Ops, 2); + } + case Expr::ArraySubscriptExprClass: { + ArraySubscriptExpr* ASExpr = cast<ArraySubscriptExpr>(E); + llvm::Constant *Base = Visit(ASExpr->getBase()); + llvm::Constant *Index = Visit(ASExpr->getIdx()); + assert(!ASExpr->getBase()->getType()->isVectorType() && + "Taking the address of a vector component is illegal!"); + return llvm::ConstantExpr::getGetElementPtr(Base, &Index, 1); + } + case Expr::StringLiteralClass: { + StringLiteral *String = cast<StringLiteral>(E); + assert(!String->isWide() && "Cannot codegen wide strings yet"); + const char *StrData = String->getStrData(); + unsigned Len = String->getByteLength(); + + return CGM.GetAddrOfConstantString(std::string(StrData, StrData + Len)); + } + case Expr::UnaryOperatorClass: { + UnaryOperator *Exp = cast<UnaryOperator>(E); + switch (Exp->getOpcode()) { + default: break; + case UnaryOperator::Extension: + // Extension is just a wrapper for expressions + return EmitLValue(Exp->getSubExpr()); + case UnaryOperator::Real: + case UnaryOperator::Imag: { + // The address of __real or __imag is just a GEP off the address + // of the internal expression + llvm::Constant* C = EmitLValue(Exp->getSubExpr()); + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, + Exp->getOpcode() == UnaryOperator::Imag); + llvm::Value *Ops[] = {Zero, Idx}; + return llvm::ConstantExpr::getGetElementPtr(C, Ops, 2); + } + case UnaryOperator::Deref: + // The address of a deref is just the value of the expression + return Visit(Exp->getSubExpr()); + } + break; + } + } + CGM.WarnUnsupported(E, "constant l-value expression"); + llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); + return llvm::UndefValue::get(Ty); + } + +}; + +} // end anonymous namespace. + + +llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, + CodeGenFunction *CGF) +{ + QualType type = E->getType().getCanonicalType(); + + if (type->isIntegerType()) { + llvm::APSInt Value(static_cast<uint32_t>(Context.getTypeSize(type))); + if (E->isIntegerConstantExpr(Value, Context)) { + return llvm::ConstantInt::get(Value); + } + } + + return ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E)); +} diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp new file mode 100644 index 00000000000..892712a0d4c --- /dev/null +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -0,0 +1,1185 @@ +//===--- CGExprScalar.cpp - Emit LLVM Code for Scalar Exprs ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Expr nodes with scalar LLVM types as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/AST.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Intrinsics.h" +#include "llvm/Support/Compiler.h" +#include <cstdarg> + +using namespace clang; +using namespace CodeGen; +using llvm::Value; + +//===----------------------------------------------------------------------===// +// Scalar Expression Emitter +//===----------------------------------------------------------------------===// + +struct BinOpInfo { + Value *LHS; + Value *RHS; + QualType Ty; // Computation Type. + const BinaryOperator *E; +}; + +namespace { +class VISIBILITY_HIDDEN ScalarExprEmitter + : public StmtVisitor<ScalarExprEmitter, Value*> { + CodeGenFunction &CGF; + llvm::LLVMFoldingBuilder &Builder; + CGObjCRuntime *Runtime; + + +public: + + ScalarExprEmitter(CodeGenFunction &cgf) : CGF(cgf), + Builder(CGF.Builder), + Runtime(CGF.CGM.getObjCRuntime()) { + } + + + //===--------------------------------------------------------------------===// + // Utilities + //===--------------------------------------------------------------------===// + + const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); } + LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); } + + Value *EmitLoadOfLValue(LValue LV, QualType T) { + return CGF.EmitLoadOfLValue(LV, T).getScalarVal(); + } + + /// EmitLoadOfLValue - Given an expression with complex type that represents a + /// value l-value, this method emits the address of the l-value, then loads + /// and returns the result. + Value *EmitLoadOfLValue(const Expr *E) { + // FIXME: Volatile + return EmitLoadOfLValue(EmitLValue(E), E->getType()); + } + + /// EmitConversionToBool - Convert the specified expression value to a + /// boolean (i1) truth value. This is equivalent to "Val != 0". + Value *EmitConversionToBool(Value *Src, QualType DstTy); + + /// EmitScalarConversion - Emit a conversion from the specified type to the + /// specified destination type, both of which are LLVM scalar types. + Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy); + + /// EmitComplexToScalarConversion - Emit a conversion from the specified + /// complex type to the specified destination type, where the destination + /// type is an LLVM scalar type. + Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, + QualType SrcTy, QualType DstTy); + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + Value *VisitStmt(Stmt *S) { + S->dump(CGF.getContext().getSourceManager()); + assert(0 && "Stmt can't have complex result type!"); + return 0; + } + Value *VisitExpr(Expr *S); + Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); } + + // Leaves. + Value *VisitIntegerLiteral(const IntegerLiteral *E) { + return llvm::ConstantInt::get(E->getValue()); + } + Value *VisitFloatingLiteral(const FloatingLiteral *E) { + return llvm::ConstantFP::get(ConvertType(E->getType()), E->getValue()); + } + Value *VisitCharacterLiteral(const CharacterLiteral *E) { + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); + } + Value *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); + } + Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) { + return llvm::ConstantInt::get(ConvertType(E->getType()), + CGF.getContext().typesAreCompatible( + E->getArgType1(), E->getArgType2())); + } + Value *VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) { + return EmitSizeAlignOf(E->getArgumentType(), E->getType(), E->isSizeOf()); + } + + // l-values. + Value *VisitDeclRefExpr(DeclRefExpr *E) { + if (const EnumConstantDecl *EC = dyn_cast<EnumConstantDecl>(E->getDecl())) + return llvm::ConstantInt::get(EC->getInitVal()); + return EmitLoadOfLValue(E); + } + Value *VisitObjCMessageExpr(ObjCMessageExpr *E); + Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); + Value *VisitMemberExpr(Expr *E) { return EmitLoadOfLValue(E); } + Value *VisitOCUVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } + Value *VisitStringLiteral(Expr *E) { return EmitLValue(E).getAddress(); } + Value *VisitPreDefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); } + + Value *VisitInitListExpr(InitListExpr *E) { + unsigned NumInitElements = E->getNumInits(); + + const llvm::VectorType *VType = + dyn_cast<llvm::VectorType>(ConvertType(E->getType())); + + // We have a scalar in braces. Just use the first element. + if (!VType) + return Visit(E->getInit(0)); + + unsigned NumVectorElements = VType->getNumElements(); + const llvm::Type *ElementType = VType->getElementType(); + + // Emit individual vector element stores. + llvm::Value *V = llvm::UndefValue::get(VType); + + // Emit initializers + unsigned i; + for (i = 0; i < NumInitElements; ++i) { + Value *NewV = Visit(E->getInit(i)); + Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + V = Builder.CreateInsertElement(V, NewV, Idx); + } + + // Emit remaining default initializers + for (/* Do not initialize i*/; i < NumVectorElements; ++i) { + Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + llvm::Value *NewV = llvm::Constant::getNullValue(ElementType); + V = Builder.CreateInsertElement(V, NewV, Idx); + } + + return V; + } + + Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + return Visit(E->getInitializer()); + } + + Value *VisitImplicitCastExpr(const ImplicitCastExpr *E); + Value *VisitCastExpr(const CastExpr *E) { + return EmitCastExpr(E->getSubExpr(), E->getType()); + } + Value *EmitCastExpr(const Expr *E, QualType T); + + Value *VisitCallExpr(const CallExpr *E) { + return CGF.EmitCallExpr(E).getScalarVal(); + } + + Value *VisitStmtExpr(const StmtExpr *E); + + // Unary Operators. + Value *VisitPrePostIncDec(const UnaryOperator *E, bool isInc, bool isPre); + Value *VisitUnaryPostDec(const UnaryOperator *E) { + return VisitPrePostIncDec(E, false, false); + } + Value *VisitUnaryPostInc(const UnaryOperator *E) { + return VisitPrePostIncDec(E, true, false); + } + Value *VisitUnaryPreDec(const UnaryOperator *E) { + return VisitPrePostIncDec(E, false, true); + } + Value *VisitUnaryPreInc(const UnaryOperator *E) { + return VisitPrePostIncDec(E, true, true); + } + Value *VisitUnaryAddrOf(const UnaryOperator *E) { + return EmitLValue(E->getSubExpr()).getAddress(); + } + Value *VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); } + Value *VisitUnaryPlus(const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + Value *VisitUnaryMinus (const UnaryOperator *E); + Value *VisitUnaryNot (const UnaryOperator *E); + Value *VisitUnaryLNot (const UnaryOperator *E); + Value *VisitUnarySizeOf (const UnaryOperator *E) { + return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), true); + } + Value *VisitUnaryAlignOf (const UnaryOperator *E) { + return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), false); + } + Value *EmitSizeAlignOf(QualType TypeToSize, QualType RetType, + bool isSizeOf); + Value *VisitUnaryReal (const UnaryOperator *E); + Value *VisitUnaryImag (const UnaryOperator *E); + Value *VisitUnaryExtension(const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + Value *VisitUnaryOffsetOf(const UnaryOperator *E); + + // Binary Operators. + Value *EmitMul(const BinOpInfo &Ops) { + return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul"); + } + Value *EmitDiv(const BinOpInfo &Ops); + Value *EmitRem(const BinOpInfo &Ops); + Value *EmitAdd(const BinOpInfo &Ops); + Value *EmitSub(const BinOpInfo &Ops); + Value *EmitShl(const BinOpInfo &Ops); + Value *EmitShr(const BinOpInfo &Ops); + Value *EmitAnd(const BinOpInfo &Ops) { + return Builder.CreateAnd(Ops.LHS, Ops.RHS, "and"); + } + Value *EmitXor(const BinOpInfo &Ops) { + return Builder.CreateXor(Ops.LHS, Ops.RHS, "xor"); + } + Value *EmitOr (const BinOpInfo &Ops) { + return Builder.CreateOr(Ops.LHS, Ops.RHS, "or"); + } + + BinOpInfo EmitBinOps(const BinaryOperator *E); + Value *EmitCompoundAssign(const CompoundAssignOperator *E, + Value *(ScalarExprEmitter::*F)(const BinOpInfo &)); + + // Binary operators and binary compound assignment operators. +#define HANDLEBINOP(OP) \ + Value *VisitBin ## OP(const BinaryOperator *E) { \ + return Emit ## OP(EmitBinOps(E)); \ + } \ + Value *VisitBin ## OP ## Assign(const CompoundAssignOperator *E) { \ + return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP); \ + } + HANDLEBINOP(Mul); + HANDLEBINOP(Div); + HANDLEBINOP(Rem); + HANDLEBINOP(Add); + // (Sub) - Sub is handled specially below for ptr-ptr subtract. + HANDLEBINOP(Shl); + HANDLEBINOP(Shr); + HANDLEBINOP(And); + HANDLEBINOP(Xor); + HANDLEBINOP(Or); +#undef HANDLEBINOP + Value *VisitBinSub(const BinaryOperator *E); + Value *VisitBinSubAssign(const CompoundAssignOperator *E) { + return EmitCompoundAssign(E, &ScalarExprEmitter::EmitSub); + } + + // Comparisons. + Value *EmitCompare(const BinaryOperator *E, unsigned UICmpOpc, + unsigned SICmpOpc, unsigned FCmpOpc); +#define VISITCOMP(CODE, UI, SI, FP) \ + Value *VisitBin##CODE(const BinaryOperator *E) { \ + return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \ + llvm::FCmpInst::FP); } + VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT); + VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT); + VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE); + VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE); + VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ); + VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE); +#undef VISITCOMP + + Value *VisitBinAssign (const BinaryOperator *E); + + Value *VisitBinLAnd (const BinaryOperator *E); + Value *VisitBinLOr (const BinaryOperator *E); + Value *VisitBinComma (const BinaryOperator *E); + + // Other Operators. + Value *VisitConditionalOperator(const ConditionalOperator *CO); + Value *VisitChooseExpr(ChooseExpr *CE); + Value *VisitOverloadExpr(OverloadExpr *OE); + Value *VisitVAArgExpr(VAArgExpr *VE); + Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) { + return CGF.EmitObjCStringLiteral(E); + } + Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E); +}; +} // end anonymous namespace. + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +/// EmitConversionToBool - Convert the specified expression value to a +/// boolean (i1) truth value. This is equivalent to "Val != 0". +Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { + assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs"); + + if (SrcType->isRealFloatingType()) { + // Compare against 0.0 for fp scalars. + llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType()); + return Builder.CreateFCmpUNE(Src, Zero, "tobool"); + } + + assert((SrcType->isIntegerType() || SrcType->isPointerType()) && + "Unknown scalar type to convert"); + + // Because of the type rules of C, we often end up computing a logical value, + // then zero extending it to int, then wanting it as a logical value again. + // Optimize this common case. + if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(Src)) { + if (ZI->getOperand(0)->getType() == llvm::Type::Int1Ty) { + Value *Result = ZI->getOperand(0); + // If there aren't any more uses, zap the instruction to save space. + // Note that there can be more uses, for example if this + // is the result of an assignment. + if (ZI->use_empty()) + ZI->eraseFromParent(); + return Result; + } + } + + // Compare against an integer or pointer null. + llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType()); + return Builder.CreateICmpNE(Src, Zero, "tobool"); +} + +/// EmitScalarConversion - Emit a conversion from the specified type to the +/// specified destination type, both of which are LLVM scalar types. +Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, + QualType DstType) { + SrcType = SrcType.getCanonicalType(); + DstType = DstType.getCanonicalType(); + if (SrcType == DstType) return Src; + + if (DstType->isVoidType()) return 0; + + // Handle conversions to bool first, they are special: comparisons against 0. + if (DstType->isBooleanType()) + return EmitConversionToBool(Src, SrcType); + + const llvm::Type *DstTy = ConvertType(DstType); + + // Ignore conversions like int -> uint. + if (Src->getType() == DstTy) + return Src; + + // Handle pointer conversions next: pointers can only be converted to/from + // other pointers and integers. + if (isa<PointerType>(DstType)) { + // The source value may be an integer, or a pointer. + if (isa<llvm::PointerType>(Src->getType())) + return Builder.CreateBitCast(Src, DstTy, "conv"); + assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); + return Builder.CreateIntToPtr(Src, DstTy, "conv"); + } + + if (isa<PointerType>(SrcType)) { + // Must be an ptr to int cast. + assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?"); + return Builder.CreatePtrToInt(Src, DstTy, "conv"); + } + + // A scalar source can be splatted to an OCU vector of the same element type + if (DstType->isOCUVectorType() && !isa<VectorType>(SrcType) && + cast<llvm::VectorType>(DstTy)->getElementType() == Src->getType()) + return CGF.EmitVector(&Src, DstType->getAsVectorType()->getNumElements(), + true); + + // Allow bitcast from vector to integer/fp of the same size. + if (isa<llvm::VectorType>(Src->getType()) || + isa<llvm::VectorType>(DstTy)) + return Builder.CreateBitCast(Src, DstTy, "conv"); + + // Finally, we have the arithmetic types: real int/float. + if (isa<llvm::IntegerType>(Src->getType())) { + bool InputSigned = SrcType->isSignedIntegerType(); + if (isa<llvm::IntegerType>(DstTy)) + return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); + else if (InputSigned) + return Builder.CreateSIToFP(Src, DstTy, "conv"); + else + return Builder.CreateUIToFP(Src, DstTy, "conv"); + } + + assert(Src->getType()->isFloatingPoint() && "Unknown real conversion"); + if (isa<llvm::IntegerType>(DstTy)) { + if (DstType->isSignedIntegerType()) + return Builder.CreateFPToSI(Src, DstTy, "conv"); + else + return Builder.CreateFPToUI(Src, DstTy, "conv"); + } + + assert(DstTy->isFloatingPoint() && "Unknown real conversion"); + if (DstTy->getTypeID() < Src->getType()->getTypeID()) + return Builder.CreateFPTrunc(Src, DstTy, "conv"); + else + return Builder.CreateFPExt(Src, DstTy, "conv"); +} + +/// EmitComplexToScalarConversion - Emit a conversion from the specified +/// complex type to the specified destination type, where the destination +/// type is an LLVM scalar type. +Value *ScalarExprEmitter:: +EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, + QualType SrcTy, QualType DstTy) { + // Get the source element type. + SrcTy = cast<ComplexType>(SrcTy.getCanonicalType())->getElementType(); + + // Handle conversions to bool first, they are special: comparisons against 0. + if (DstTy->isBooleanType()) { + // Complex != 0 -> (Real != 0) | (Imag != 0) + Src.first = EmitScalarConversion(Src.first, SrcTy, DstTy); + Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy); + return Builder.CreateOr(Src.first, Src.second, "tobool"); + } + + // C99 6.3.1.7p2: "When a value of complex type is converted to a real type, + // the imaginary part of the complex value is discarded and the value of the + // real part is converted according to the conversion rules for the + // corresponding real type. + return EmitScalarConversion(Src.first, SrcTy, DstTy); +} + + +//===----------------------------------------------------------------------===// +// Visitor Methods +//===----------------------------------------------------------------------===// + +Value *ScalarExprEmitter::VisitExpr(Expr *E) { + CGF.WarnUnsupported(E, "scalar expression"); + if (E->getType()->isVoidType()) + return 0; + return llvm::UndefValue::get(CGF.ConvertType(E->getType())); +} + +Value *ScalarExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) { + // Only the lookup mechanism and first two arguments of the method + // implementation vary between runtimes. We can get the receiver and + // arguments in generic code. + + // Find the receiver + llvm::Value * Receiver = CGF.EmitScalarExpr(E->getReceiver()); + + // Process the arguments + unsigned int ArgC = E->getNumArgs(); + llvm::SmallVector<llvm::Value*, 16> Args; + for(unsigned i=0 ; i<ArgC ; i++) { + Expr *ArgExpr = E->getArg(i); + QualType ArgTy = ArgExpr->getType(); + if (!CGF.hasAggregateLLVMType(ArgTy)) { + // Scalar argument is passed by-value. + Args.push_back(CGF.EmitScalarExpr(ArgExpr)); + } else if (ArgTy->isComplexType()) { + // Make a temporary alloca to pass the argument. + llvm::Value *DestMem = CGF.CreateTempAlloca(ConvertType(ArgTy)); + CGF.EmitComplexExprIntoAddr(ArgExpr, DestMem, false); + Args.push_back(DestMem); + } else { + llvm::Value *DestMem = CGF.CreateTempAlloca(ConvertType(ArgTy)); + CGF.EmitAggExpr(ArgExpr, DestMem, false); + Args.push_back(DestMem); + } + } + + // Get the selector string + std::string SelStr = E->getSelector().getName(); + llvm::Constant *Selector = CGF.CGM.GetAddrOfConstantString(SelStr); + ConvertType(E->getType()); + return Runtime->generateMessageSend(Builder, + ConvertType(E->getType()), + Receiver, + Selector, + &Args[0], + Args.size()); +} + +Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + // Emit subscript expressions in rvalue context's. For most cases, this just + // loads the lvalue formed by the subscript expr. However, we have to be + // careful, because the base of a vector subscript is occasionally an rvalue, + // so we can't get it as an lvalue. + if (!E->getBase()->getType()->isVectorType()) + return EmitLoadOfLValue(E); + + // Handle the vector case. The base must be a vector, the index must be an + // integer value. + Value *Base = Visit(E->getBase()); + Value *Idx = Visit(E->getIdx()); + + // FIXME: Convert Idx to i32 type. + return Builder.CreateExtractElement(Base, Idx, "vecext"); +} + +/// VisitImplicitCastExpr - Implicit casts are the same as normal casts, but +/// also handle things like function to pointer-to-function decay, and array to +/// pointer decay. +Value *ScalarExprEmitter::VisitImplicitCastExpr(const ImplicitCastExpr *E) { + const Expr *Op = E->getSubExpr(); + + // If this is due to array->pointer conversion, emit the array expression as + // an l-value. + if (Op->getType()->isArrayType()) { + // FIXME: For now we assume that all source arrays map to LLVM arrays. This + // will not true when we add support for VLAs. + Value *V = EmitLValue(Op).getAddress(); // Bitfields can't be arrays. + + assert(isa<llvm::PointerType>(V->getType()) && + isa<llvm::ArrayType>(cast<llvm::PointerType>(V->getType()) + ->getElementType()) && + "Doesn't support VLAs yet!"); + llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + + llvm::Value *Ops[] = {Idx0, Idx0}; + V = Builder.CreateGEP(V, Ops, Ops+2, "arraydecay"); + + // The resultant pointer type can be implicitly casted to other pointer + // types as well, for example void*. + const llvm::Type *DestPTy = ConvertType(E->getType()); + assert(isa<llvm::PointerType>(DestPTy) && + "Only expect implicit cast to pointer"); + if (V->getType() != DestPTy) + V = Builder.CreateBitCast(V, DestPTy, "ptrconv"); + return V; + + } else if (E->getType()->isReferenceType()) { + assert(cast<ReferenceType>(E->getType().getCanonicalType())-> + getReferenceeType() == + Op->getType().getCanonicalType() && "Incompatible types!"); + + return EmitLValue(Op).getAddress(); + } + + return EmitCastExpr(Op, E->getType()); +} + + +// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts +// have to handle a more broad range of conversions than explicit casts, as they +// handle things like function to ptr-to-function decay etc. +Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy) { + // Handle cases where the source is an non-complex type. + + if (!CGF.hasAggregateLLVMType(E->getType())) { + Value *Src = Visit(const_cast<Expr*>(E)); + + // Use EmitScalarConversion to perform the conversion. + return EmitScalarConversion(Src, E->getType(), DestTy); + } + + if (E->getType()->isComplexType()) { + // Handle cases where the source is a complex type. + return EmitComplexToScalarConversion(CGF.EmitComplexExpr(E), E->getType(), + DestTy); + } + + // Okay, this is a cast from an aggregate. It must be a cast to void. Just + // evaluate the result and return. + CGF.EmitAggExpr(E, 0, false); + return 0; +} + +Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) { + return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getScalarVal(); +} + + +//===----------------------------------------------------------------------===// +// Unary Operators +//===----------------------------------------------------------------------===// + +Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, + bool isInc, bool isPre) { + LValue LV = EmitLValue(E->getSubExpr()); + // FIXME: Handle volatile! + Value *InVal = CGF.EmitLoadOfLValue(LV, // false + E->getSubExpr()->getType()).getScalarVal(); + + int AmountVal = isInc ? 1 : -1; + + Value *NextVal; + if (isa<llvm::PointerType>(InVal->getType())) { + // FIXME: This isn't right for VLAs. + NextVal = llvm::ConstantInt::get(llvm::Type::Int32Ty, AmountVal); + NextVal = Builder.CreateGEP(InVal, NextVal); + } else { + // Add the inc/dec to the real part. + if (isa<llvm::IntegerType>(InVal->getType())) + NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal); + else if (InVal->getType() == llvm::Type::FloatTy) + // FIXME: Handle long double. + NextVal = + llvm::ConstantFP::get(InVal->getType(), + llvm::APFloat(static_cast<float>(AmountVal))); + else { + // FIXME: Handle long double. + assert(InVal->getType() == llvm::Type::DoubleTy); + NextVal = + llvm::ConstantFP::get(InVal->getType(), + llvm::APFloat(static_cast<double>(AmountVal))); + } + NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec"); + } + + // Store the updated result through the lvalue. + CGF.EmitStoreThroughLValue(RValue::get(NextVal), LV, + E->getSubExpr()->getType()); + + // If this is a postinc, return the value read from memory, otherwise use the + // updated value. + return isPre ? NextVal : InVal; +} + + +Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { + Value *Op = Visit(E->getSubExpr()); + return Builder.CreateNeg(Op, "neg"); +} + +Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) { + Value *Op = Visit(E->getSubExpr()); + return Builder.CreateNot(Op, "neg"); +} + +Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) { + // Compare operand to zero. + Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr()); + + // Invert value. + // TODO: Could dynamically modify easy computations here. For example, if + // the operand is an icmp ne, turn into icmp eq. + BoolVal = Builder.CreateNot(BoolVal, "lnot"); + + // ZExt result to int. + return Builder.CreateZExt(BoolVal, CGF.LLVMIntTy, "lnot.ext"); +} + +/// EmitSizeAlignOf - Return the size or alignment of the 'TypeToSize' type as +/// an integer (RetType). +Value *ScalarExprEmitter::EmitSizeAlignOf(QualType TypeToSize, + QualType RetType,bool isSizeOf){ + assert(RetType->isIntegerType() && "Result type must be an integer!"); + uint32_t ResultWidth = + static_cast<uint32_t>(CGF.getContext().getTypeSize(RetType)); + + // sizeof(void) and __alignof__(void) = 1 as a gcc extension. + if (TypeToSize->isVoidType()) + return llvm::ConstantInt::get(llvm::APInt(ResultWidth, 1)); + + /// FIXME: This doesn't handle VLAs yet! + std::pair<uint64_t, unsigned> Info = CGF.getContext().getTypeInfo(TypeToSize); + + uint64_t Val = isSizeOf ? Info.first : Info.second; + Val /= 8; // Return size in bytes, not bits. + + return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val)); +} + +Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) { + Expr *Op = E->getSubExpr(); + if (Op->getType()->isComplexType()) + return CGF.EmitComplexExpr(Op).first; + return Visit(Op); +} +Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { + Expr *Op = E->getSubExpr(); + if (Op->getType()->isComplexType()) + return CGF.EmitComplexExpr(Op).second; + + // __imag on a scalar returns zero. Emit it the subexpr to ensure side + // effects are evaluated. + CGF.EmitScalarExpr(Op); + return llvm::Constant::getNullValue(ConvertType(E->getType())); +} + +Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E) +{ + int64_t Val = E->evaluateOffsetOf(CGF.getContext()); + + assert(E->getType()->isIntegerType() && "Result type must be an integer!"); + + uint32_t ResultWidth = + static_cast<uint32_t>(CGF.getContext().getTypeSize(E->getType())); + return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val)); +} + +//===----------------------------------------------------------------------===// +// Binary Operators +//===----------------------------------------------------------------------===// + +BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) { + BinOpInfo Result; + Result.LHS = Visit(E->getLHS()); + Result.RHS = Visit(E->getRHS()); + Result.Ty = E->getType(); + Result.E = E; + return Result; +} + +Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, + Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { + QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType(); + + BinOpInfo OpInfo; + + // Load the LHS and RHS operands. + LValue LHSLV = EmitLValue(E->getLHS()); + OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy); + + // Determine the computation type. If the RHS is complex, then this is one of + // the add/sub/mul/div operators. All of these operators can be computed in + // with just their real component even though the computation domain really is + // complex. + QualType ComputeType = E->getComputationType(); + + // If the computation type is complex, then the RHS is complex. Emit the RHS. + if (const ComplexType *CT = ComputeType->getAsComplexType()) { + ComputeType = CT->getElementType(); + + // Emit the RHS, only keeping the real component. + OpInfo.RHS = CGF.EmitComplexExpr(E->getRHS()).first; + RHSTy = RHSTy->getAsComplexType()->getElementType(); + } else { + // Otherwise the RHS is a simple scalar value. + OpInfo.RHS = Visit(E->getRHS()); + } + + // Convert the LHS/RHS values to the computation type. + OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, ComputeType); + + // Do not merge types for -= or += where the LHS is a pointer. + if (!(E->getOpcode() == BinaryOperator::SubAssign || + E->getOpcode() == BinaryOperator::AddAssign) || + !E->getLHS()->getType()->isPointerType()) { + OpInfo.RHS = EmitScalarConversion(OpInfo.RHS, RHSTy, ComputeType); + } + OpInfo.Ty = ComputeType; + OpInfo.E = E; + + // Expand the binary operator. + Value *Result = (this->*Func)(OpInfo); + + // Truncate the result back to the LHS type. + Result = EmitScalarConversion(Result, ComputeType, LHSTy); + + // Store the result value into the LHS lvalue. + CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, E->getType()); + + return Result; +} + + +Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { + if (Ops.LHS->getType()->isFPOrFPVector()) + return Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div"); + else if (Ops.Ty->isUnsignedIntegerType()) + return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div"); + else + return Builder.CreateSDiv(Ops.LHS, Ops.RHS, "div"); +} + +Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { + // Rem in C can't be a floating point type: C99 6.5.5p2. + if (Ops.Ty->isUnsignedIntegerType()) + return Builder.CreateURem(Ops.LHS, Ops.RHS, "rem"); + else + return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem"); +} + + +Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { + if (!Ops.Ty->isPointerType()) + return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add"); + + // FIXME: What about a pointer to a VLA? + Value *Ptr, *Idx; + Expr *IdxExp; + if (isa<llvm::PointerType>(Ops.LHS->getType())) { // pointer + int + Ptr = Ops.LHS; + Idx = Ops.RHS; + IdxExp = Ops.E->getRHS(); + } else { // int + pointer + Ptr = Ops.RHS; + Idx = Ops.LHS; + IdxExp = Ops.E->getLHS(); + } + + unsigned Width = cast<llvm::IntegerType>(Idx->getType())->getBitWidth(); + if (Width < CGF.LLVMPointerWidth) { + // Zero or sign extend the pointer value based on whether the index is + // signed or not. + const llvm::Type *IdxType = llvm::IntegerType::get(CGF.LLVMPointerWidth); + if (IdxExp->getType().getCanonicalType()->isSignedIntegerType()) + Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); + else + Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); + } + + return Builder.CreateGEP(Ptr, Idx, "add.ptr"); +} + +Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { + if (!isa<llvm::PointerType>(Ops.LHS->getType())) + return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub"); + + // pointer - int + assert(!isa<llvm::PointerType>(Ops.RHS->getType()) && + "ptr-ptr shouldn't get here"); + // FIXME: The pointer could point to a VLA. + Value *Idx = Builder.CreateNeg(Ops.RHS, "sub.ptr.neg"); + + unsigned Width = cast<llvm::IntegerType>(Idx->getType())->getBitWidth(); + if (Width < CGF.LLVMPointerWidth) { + // Zero or sign extend the pointer value based on whether the index is + // signed or not. + const llvm::Type *IdxType = llvm::IntegerType::get(CGF.LLVMPointerWidth); + if (Ops.E->getRHS()->getType().getCanonicalType()->isSignedIntegerType()) + Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); + else + Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); + } + + return Builder.CreateGEP(Ops.LHS, Idx, "sub.ptr"); +} + +Value *ScalarExprEmitter::VisitBinSub(const BinaryOperator *E) { + // "X - Y" is different from "X -= Y" in one case: when Y is a pointer. In + // the compound assignment case it is invalid, so just handle it here. + if (!E->getRHS()->getType()->isPointerType()) + return EmitSub(EmitBinOps(E)); + + // pointer - pointer + Value *LHS = Visit(E->getLHS()); + Value *RHS = Visit(E->getRHS()); + + const QualType LHSType = E->getLHS()->getType().getCanonicalType(); + const QualType LHSElementType = cast<PointerType>(LHSType)->getPointeeType(); + uint64_t ElementSize = CGF.getContext().getTypeSize(LHSElementType) / 8; + + const llvm::Type *ResultType = ConvertType(E->getType()); + LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast"); + RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); + Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub"); + + // HACK: LLVM doesn't have an divide instruction that 'knows' there is no + // remainder. As such, we handle common power-of-two cases here to generate + // better code. + if (llvm::isPowerOf2_64(ElementSize)) { + Value *ShAmt = + llvm::ConstantInt::get(ResultType, llvm::Log2_64(ElementSize)); + return Builder.CreateAShr(BytesBetween, ShAmt, "sub.ptr.shr"); + } + + // Otherwise, do a full sdiv. + Value *BytesPerElt = llvm::ConstantInt::get(ResultType, ElementSize); + return Builder.CreateSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); +} + + +Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { + // LLVM requires the LHS and RHS to be the same type: promote or truncate the + // RHS to the same size as the LHS. + Value *RHS = Ops.RHS; + if (Ops.LHS->getType() != RHS->getType()) + RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); + + return Builder.CreateShl(Ops.LHS, RHS, "shl"); +} + +Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { + // LLVM requires the LHS and RHS to be the same type: promote or truncate the + // RHS to the same size as the LHS. + Value *RHS = Ops.RHS; + if (Ops.LHS->getType() != RHS->getType()) + RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); + + if (Ops.Ty->isUnsignedIntegerType()) + return Builder.CreateLShr(Ops.LHS, RHS, "shr"); + return Builder.CreateAShr(Ops.LHS, RHS, "shr"); +} + +Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, + unsigned SICmpOpc, unsigned FCmpOpc) { + Value *Result; + QualType LHSTy = E->getLHS()->getType(); + if (!LHSTy->isComplexType()) { + Value *LHS = Visit(E->getLHS()); + Value *RHS = Visit(E->getRHS()); + + if (LHS->getType()->isFloatingPoint()) { + Result = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc, + LHS, RHS, "cmp"); + } else if (LHSTy->isUnsignedIntegerType()) { + Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc, + LHS, RHS, "cmp"); + } else { + // Signed integers and pointers. + Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)SICmpOpc, + LHS, RHS, "cmp"); + } + } else { + // Complex Comparison: can only be an equality comparison. + CodeGenFunction::ComplexPairTy LHS = CGF.EmitComplexExpr(E->getLHS()); + CodeGenFunction::ComplexPairTy RHS = CGF.EmitComplexExpr(E->getRHS()); + + QualType CETy = + cast<ComplexType>(LHSTy.getCanonicalType())->getElementType(); + + Value *ResultR, *ResultI; + if (CETy->isRealFloatingType()) { + ResultR = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc, + LHS.first, RHS.first, "cmp.r"); + ResultI = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc, + LHS.second, RHS.second, "cmp.i"); + } else { + // Complex comparisons can only be equality comparisons. As such, signed + // and unsigned opcodes are the same. + ResultR = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc, + LHS.first, RHS.first, "cmp.r"); + ResultI = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc, + LHS.second, RHS.second, "cmp.i"); + } + + if (E->getOpcode() == BinaryOperator::EQ) { + Result = Builder.CreateAnd(ResultR, ResultI, "and.ri"); + } else { + assert(E->getOpcode() == BinaryOperator::NE && + "Complex comparison other than == or != ?"); + Result = Builder.CreateOr(ResultR, ResultI, "or.ri"); + } + } + + // ZExt result to int. + return Builder.CreateZExt(Result, CGF.LLVMIntTy, "cmp.ext"); +} + +Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { + LValue LHS = EmitLValue(E->getLHS()); + Value *RHS = Visit(E->getRHS()); + + // Store the value into the LHS. + // FIXME: Volatility! + CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS, E->getType()); + + // Return the RHS. + return RHS; +} + +Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { + Value *LHSCond = CGF.EvaluateExprAsBool(E->getLHS()); + + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("land_cont"); + llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("land_rhs"); + + llvm::BasicBlock *OrigBlock = Builder.GetInsertBlock(); + Builder.CreateCondBr(LHSCond, RHSBlock, ContBlock); + + CGF.EmitBlock(RHSBlock); + Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); + + // Reaquire the RHS block, as there may be subblocks inserted. + RHSBlock = Builder.GetInsertBlock(); + CGF.EmitBlock(ContBlock); + + // Create a PHI node. If we just evaluted the LHS condition, the result is + // false. If we evaluated both, the result is the RHS condition. + llvm::PHINode *PN = Builder.CreatePHI(llvm::Type::Int1Ty, "land"); + PN->reserveOperandSpace(2); + PN->addIncoming(llvm::ConstantInt::getFalse(), OrigBlock); + PN->addIncoming(RHSCond, RHSBlock); + + // ZExt result to int. + return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext"); +} + +Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { + Value *LHSCond = CGF.EvaluateExprAsBool(E->getLHS()); + + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("lor_cont"); + llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("lor_rhs"); + + llvm::BasicBlock *OrigBlock = Builder.GetInsertBlock(); + Builder.CreateCondBr(LHSCond, ContBlock, RHSBlock); + + CGF.EmitBlock(RHSBlock); + Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); + + // Reaquire the RHS block, as there may be subblocks inserted. + RHSBlock = Builder.GetInsertBlock(); + CGF.EmitBlock(ContBlock); + + // Create a PHI node. If we just evaluted the LHS condition, the result is + // true. If we evaluated both, the result is the RHS condition. + llvm::PHINode *PN = Builder.CreatePHI(llvm::Type::Int1Ty, "lor"); + PN->reserveOperandSpace(2); + PN->addIncoming(llvm::ConstantInt::getTrue(), OrigBlock); + PN->addIncoming(RHSCond, RHSBlock); + + // ZExt result to int. + return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext"); +} + +Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) { + CGF.EmitStmt(E->getLHS()); + return Visit(E->getRHS()); +} + +//===----------------------------------------------------------------------===// +// Other Operators +//===----------------------------------------------------------------------===// + +Value *ScalarExprEmitter:: +VisitConditionalOperator(const ConditionalOperator *E) { + llvm::BasicBlock *LHSBlock = new llvm::BasicBlock("cond.?"); + llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:"); + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont"); + + // Evaluate the conditional, then convert it to bool. We do this explicitly + // because we need the unconverted value if this is a GNU ?: expression with + // missing middle value. + Value *CondVal = CGF.EmitScalarExpr(E->getCond()); + Value *CondBoolVal =CGF.EmitScalarConversion(CondVal, E->getCond()->getType(), + CGF.getContext().BoolTy); + Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock); + + CGF.EmitBlock(LHSBlock); + + // Handle the GNU extension for missing LHS. + Value *LHS; + if (E->getLHS()) + LHS = Visit(E->getLHS()); + else // Perform promotions, to handle cases like "short ?: int" + LHS = EmitScalarConversion(CondVal, E->getCond()->getType(), E->getType()); + + Builder.CreateBr(ContBlock); + LHSBlock = Builder.GetInsertBlock(); + + CGF.EmitBlock(RHSBlock); + + Value *RHS = Visit(E->getRHS()); + Builder.CreateBr(ContBlock); + RHSBlock = Builder.GetInsertBlock(); + + CGF.EmitBlock(ContBlock); + + if (!LHS) { + assert(E->getType()->isVoidType() && "Non-void value should have a value"); + return 0; + } + + // Create a PHI node for the real part. + llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), "cond"); + PN->reserveOperandSpace(2); + PN->addIncoming(LHS, LHSBlock); + PN->addIncoming(RHS, RHSBlock); + return PN; +} + +Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) { + // Emit the LHS or RHS as appropriate. + return + Visit(E->isConditionTrue(CGF.getContext()) ? E->getLHS() : E->getRHS()); +} + +Value *ScalarExprEmitter::VisitOverloadExpr(OverloadExpr *E) { + return CGF.EmitCallExpr(E->getFn(), E->arg_begin(), + E->getNumArgs(CGF.getContext())).getScalarVal(); +} + +Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { + llvm::Value *ArgValue = EmitLValue(VE->getSubExpr()).getAddress(); + + llvm::Value *V = Builder.CreateVAArg(ArgValue, ConvertType(VE->getType())); + return V; +} + +Value *ScalarExprEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { + std::string str; + llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes; + CGF.getContext().getObjCEncodingForType(E->getEncodedType(), str, + EncodingRecordTypes); + + llvm::Constant *C = llvm::ConstantArray::get(str); + C = new llvm::GlobalVariable(C->getType(), true, + llvm::GlobalValue::InternalLinkage, + C, ".str", &CGF.CGM.getModule()); + llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty); + llvm::Constant *Zeros[] = { Zero, Zero }; + C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2); + + return C; +} + +//===----------------------------------------------------------------------===// +// Entry Point into this File +//===----------------------------------------------------------------------===// + +/// EmitComplexExpr - Emit the computation of the specified expression of +/// complex type, ignoring the result. +Value *CodeGenFunction::EmitScalarExpr(const Expr *E) { + assert(E && !hasAggregateLLVMType(E->getType()) && + "Invalid scalar expression to emit"); + + return ScalarExprEmitter(*this).Visit(const_cast<Expr*>(E)); +} + +/// EmitScalarConversion - Emit a conversion from the specified type to the +/// specified destination type, both of which are LLVM scalar types. +Value *CodeGenFunction::EmitScalarConversion(Value *Src, QualType SrcTy, + QualType DstTy) { + assert(!hasAggregateLLVMType(SrcTy) && !hasAggregateLLVMType(DstTy) && + "Invalid scalar expression to emit"); + return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy); +} + +/// EmitComplexToScalarConversion - Emit a conversion from the specified +/// complex type to the specified destination type, where the destination +/// type is an LLVM scalar type. +Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src, + QualType SrcTy, + QualType DstTy) { + assert(SrcTy->isComplexType() && !hasAggregateLLVMType(DstTy) && + "Invalid complex -> scalar conversion"); + return ScalarExprEmitter(*this).EmitComplexToScalarConversion(Src, SrcTy, + DstTy); +} + +Value *CodeGenFunction::EmitShuffleVector(Value* V1, Value *V2, ...) { + assert(V1->getType() == V2->getType() && + "Vector operands must be of the same type"); + + unsigned NumElements = + cast<llvm::VectorType>(V1->getType())->getNumElements(); + + va_list va; + va_start(va, V2); + + llvm::SmallVector<llvm::Constant*, 16> Args; + + for (unsigned i = 0; i < NumElements; i++) { + int n = va_arg(va, int); + + assert(n >= 0 && n < (int)NumElements * 2 && + "Vector shuffle index out of bounds!"); + + Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, n)); + } + + const char *Name = va_arg(va, const char *); + va_end(va); + + llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements); + + return Builder.CreateShuffleVector(V1, V2, Mask, Name); +} + +llvm::Value *CodeGenFunction::EmitVector(llvm::Value * const *Vals, + unsigned NumVals, bool isSplat) +{ + llvm::Value *Vec + = llvm::UndefValue::get(llvm::VectorType::get(Vals[0]->getType(), NumVals)); + + for (unsigned i = 0, e = NumVals ; i != e; ++i) { + llvm::Value *Val = isSplat ? Vals[0] : Vals[i]; + llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Vec = Builder.CreateInsertElement(Vec, Val, Idx, "tmp"); + } + + return Vec; +} diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp new file mode 100644 index 00000000000..33419a3d51d --- /dev/null +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -0,0 +1,25 @@ +//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Objective-C code as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/Expr.h" +#include "llvm/Constant.h" +using namespace clang; +using namespace CodeGen; + +llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){ + std::string S(E->getString()->getStrData(), E->getString()->getByteLength()); + return CGM.GetAddrOfConstantCFString(S); +} + diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp new file mode 100644 index 00000000000..f0d6f554d55 --- /dev/null +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -0,0 +1,97 @@ +//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides Objective-C code generation targetting the GNU runtime. +// +//===----------------------------------------------------------------------===// + +#include "CGObjCRuntime.h" +#include "llvm/Module.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/LLVMBuilder.h" +#include "llvm/ADT/SmallVector.h" + +using namespace clang::CodeGen; +using namespace clang; + +CGObjCRuntime::~CGObjCRuntime() {} + +namespace { +class CGObjCGNU : public CGObjCRuntime { +private: + llvm::Module &TheModule; +public: + CGObjCGNU(llvm::Module &M) : TheModule(M) {}; + virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + llvm::Constant *Selector, + llvm::Value** ArgV, + unsigned ArgC); +}; +} // end anonymous namespace + +// Generate code for a message send expression on the GNU runtime. +// BIG FAT WARNING: Much of this code will need factoring out later. +// FIXME: This currently only handles id returns. Other return types +// need some explicit casting. +llvm::Value *CGObjCGNU::generateMessageSend(llvm::LLVMFoldingBuilder &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + llvm::Constant *Selector, + llvm::Value** ArgV, + unsigned ArgC) { + // Get the selector Type. + const llvm::Type *PtrToInt8Ty = + llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + std::vector<const llvm::Type*> Str2(2, PtrToInt8Ty); + const llvm::Type *SelStructTy = llvm::StructType::get(Str2); + const llvm::Type *SelTy = llvm::PointerType::getUnqual(SelStructTy); + + // Look up the selector. + // If we haven't got the selector lookup function, look it up now. + // TODO: Factor this out and use it to implement @selector() too. + llvm::Constant *SelFunction = + TheModule.getOrInsertFunction("sel_get_uid", SelTy, PtrToInt8Ty, NULL); + // FIXME: Selectors should be statically cached, not looked up on every call. + + // TODO: Pull this out into the caller. + llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *Ops[] = {Idx0, Idx0}; + llvm::Value *SelStr = llvm::ConstantExpr::getGetElementPtr(Selector, Ops, 2); + llvm::Value *cmd = Builder.CreateCall(SelFunction, &SelStr, &SelStr+1); + + // Look up the method implementation. + std::vector<const llvm::Type*> impArgTypes; + impArgTypes.push_back(Receiver->getType()); + impArgTypes.push_back(SelTy); + + // Avoid an explicit cast on the IMP by getting a version that has the right + // return type. + llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes, + true); + + llvm::Constant *lookupFunction = + TheModule.getOrInsertFunction("objc_msg_lookup", + llvm::PointerType::get(impType, 0), + Receiver->getType(), SelTy, NULL); + llvm::SmallVector<llvm::Value*, 16> lookupArgs; + lookupArgs.push_back(Receiver); + lookupArgs.push_back(cmd); + llvm::Value *imp = Builder.CreateCall(lookupFunction, + lookupArgs.begin(), lookupArgs.end()); + + // Call the method. + lookupArgs.insert(lookupArgs.end(), ArgV, ArgV+ArgC); + return Builder.CreateCall(imp, lookupArgs.begin(), lookupArgs.end()); +} + +CGObjCRuntime * clang::CodeGen::CreateObjCRuntime(llvm::Module &M) { + return new CGObjCGNU(M); +} diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h new file mode 100644 index 00000000000..d8fc60f99c0 --- /dev/null +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -0,0 +1,47 @@ +//===----- CGObjCRuntime.h - Emit LLVM Code from ASTs for a Module --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This provides an abstract class for Objective-C code generation. Concrete +// subclasses of this implement code generation for specific Objective-C +// runtime libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_OBCJRUNTIME_H +#define CLANG_CODEGEN_OBCJRUNTIME_H + +namespace llvm { + class LLVMFoldingBuilder; + class Constant; + class Type; + class Value; + class Module; +} + +namespace clang { +namespace CodeGen { + +// Implements runtime-specific code generation functions +class CGObjCRuntime { +public: + virtual ~CGObjCRuntime(); + + // Generate an Objective-C message send operation + virtual llvm::Value *generateMessageSend(llvm::LLVMFoldingBuilder &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + llvm::Constant *Selector, + llvm::Value** ArgV, + unsigned ArgC) = 0; +}; + +CGObjCRuntime *CreateObjCRuntime(llvm::Module &M); +} +} +#endif diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp new file mode 100644 index 00000000000..5fdc61b46f8 --- /dev/null +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -0,0 +1,776 @@ +//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Stmt nodes as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "clang/AST/AST.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace CodeGen; + +//===----------------------------------------------------------------------===// +// Statement Emission +//===----------------------------------------------------------------------===// + +void CodeGenFunction::EmitStmt(const Stmt *S) { + assert(S && "Null statement?"); + + switch (S->getStmtClass()) { + default: + // Must be an expression in a stmt context. Emit the value (to get + // side-effects) and ignore the result. + if (const Expr *E = dyn_cast<Expr>(S)) { + if (!hasAggregateLLVMType(E->getType())) + EmitScalarExpr(E); + else if (E->getType()->isComplexType()) + EmitComplexExpr(E); + else + EmitAggExpr(E, 0, false); + } else { + WarnUnsupported(S, "statement"); + } + break; + case Stmt::NullStmtClass: break; + case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break; + case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break; + case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break; + + case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break; + case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break; + case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break; + case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break; + + case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break; + case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break; + + case Stmt::BreakStmtClass: EmitBreakStmt(); break; + case Stmt::ContinueStmtClass: EmitContinueStmt(); break; + case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break; + case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break; + case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break; + case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break; + } +} + +/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true, +/// this captures the expression result of the last sub-statement and returns it +/// (for use by the statement expression extension). +RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, + llvm::Value *AggLoc, bool isAggVol) { + // FIXME: handle vla's etc. + if (S.body_empty() || !isa<Expr>(S.body_back())) GetLast = false; + + for (CompoundStmt::const_body_iterator I = S.body_begin(), + E = S.body_end()-GetLast; I != E; ++I) + EmitStmt(*I); + + + if (!GetLast) + return RValue::get(0); + + return EmitAnyExpr(cast<Expr>(S.body_back()), AggLoc); +} + +void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB) { + // Emit a branch from this block to the next one if this was a real block. If + // this was just a fall-through block after a terminator, don't emit it. + llvm::BasicBlock *LastBB = Builder.GetInsertBlock(); + + if (LastBB->getTerminator()) { + // If the previous block is already terminated, don't touch it. + } else if (LastBB->empty() && LastBB->getValueName() == 0) { + // If the last block was an empty placeholder, remove it now. + // TODO: cache and reuse these. + Builder.GetInsertBlock()->eraseFromParent(); + } else { + // Otherwise, create a fall-through branch. + Builder.CreateBr(BB); + } + CurFn->getBasicBlockList().push_back(BB); + Builder.SetInsertPoint(BB); +} + +void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { + llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S); + + EmitBlock(NextBB); + EmitStmt(S.getSubStmt()); +} + +void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { + Builder.CreateBr(getBasicBlockForLabel(S.getLabel())); + + // Emit a block after the branch so that dead code after a goto has some place + // to go. + Builder.SetInsertPoint(new llvm::BasicBlock("", CurFn)); +} + +void CodeGenFunction::EmitIfStmt(const IfStmt &S) { + // C99 6.8.4.1: The first substatement is executed if the expression compares + // unequal to 0. The condition must be a scalar type. + llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); + + llvm::BasicBlock *ContBlock = new llvm::BasicBlock("ifend"); + llvm::BasicBlock *ThenBlock = new llvm::BasicBlock("ifthen"); + llvm::BasicBlock *ElseBlock = ContBlock; + + if (S.getElse()) + ElseBlock = new llvm::BasicBlock("ifelse"); + + // Insert the conditional branch. + Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock); + + // Emit the 'then' code. + EmitBlock(ThenBlock); + EmitStmt(S.getThen()); + llvm::BasicBlock *BB = Builder.GetInsertBlock(); + if (isDummyBlock(BB)) { + BB->eraseFromParent(); + Builder.SetInsertPoint(ThenBlock); + } + else + Builder.CreateBr(ContBlock); + + // Emit the 'else' code if present. + if (const Stmt *Else = S.getElse()) { + EmitBlock(ElseBlock); + EmitStmt(Else); + llvm::BasicBlock *BB = Builder.GetInsertBlock(); + if (isDummyBlock(BB)) { + BB->eraseFromParent(); + Builder.SetInsertPoint(ElseBlock); + } + else + Builder.CreateBr(ContBlock); + } + + // Emit the continuation block for code after the if. + EmitBlock(ContBlock); +} + +void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { + // Emit the header for the loop, insert it, which will create an uncond br to + // it. + llvm::BasicBlock *LoopHeader = new llvm::BasicBlock("whilecond"); + EmitBlock(LoopHeader); + + // Evaluate the conditional in the while header. C99 6.8.5.1: The evaluation + // of the controlling expression takes place before each execution of the loop + // body. + llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); + + // while(1) is common, avoid extra exit blocks. Be sure + // to correctly handle break/continue though. + bool EmitBoolCondBranch = true; + if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) + if (C->isOne()) + EmitBoolCondBranch = false; + + // Create an exit block for when the condition fails, create a block for the + // body of the loop. + llvm::BasicBlock *ExitBlock = new llvm::BasicBlock("whileexit"); + llvm::BasicBlock *LoopBody = new llvm::BasicBlock("whilebody"); + + // As long as the condition is true, go to the loop body. + if (EmitBoolCondBranch) + Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); + + // Store the blocks to use for break and continue. + BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader)); + + // Emit the loop body. + EmitBlock(LoopBody); + EmitStmt(S.getBody()); + + BreakContinueStack.pop_back(); + + // Cycle to the condition. + Builder.CreateBr(LoopHeader); + + // Emit the exit block. + EmitBlock(ExitBlock); + + // If LoopHeader is a simple forwarding block then eliminate it. + if (!EmitBoolCondBranch + && &LoopHeader->front() == LoopHeader->getTerminator()) { + LoopHeader->replaceAllUsesWith(LoopBody); + LoopHeader->getTerminator()->eraseFromParent(); + LoopHeader->eraseFromParent(); + } +} + +void CodeGenFunction::EmitDoStmt(const DoStmt &S) { + // Emit the body for the loop, insert it, which will create an uncond br to + // it. + llvm::BasicBlock *LoopBody = new llvm::BasicBlock("dobody"); + llvm::BasicBlock *AfterDo = new llvm::BasicBlock("afterdo"); + EmitBlock(LoopBody); + + llvm::BasicBlock *DoCond = new llvm::BasicBlock("docond"); + + // Store the blocks to use for break and continue. + BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond)); + + // Emit the body of the loop into the block. + EmitStmt(S.getBody()); + + BreakContinueStack.pop_back(); + + EmitBlock(DoCond); + + // C99 6.8.5.2: "The evaluation of the controlling expression takes place + // after each execution of the loop body." + + // Evaluate the conditional in the while header. + // C99 6.8.5p2/p4: The first substatement is executed if the expression + // compares unequal to 0. The condition must be a scalar type. + llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); + + // "do {} while (0)" is common in macros, avoid extra blocks. Be sure + // to correctly handle break/continue though. + bool EmitBoolCondBranch = true; + if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) + if (C->isZero()) + EmitBoolCondBranch = false; + + // As long as the condition is true, iterate the loop. + if (EmitBoolCondBranch) + Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo); + + // Emit the exit block. + EmitBlock(AfterDo); + + // If DoCond is a simple forwarding block then eliminate it. + if (!EmitBoolCondBranch && &DoCond->front() == DoCond->getTerminator()) { + DoCond->replaceAllUsesWith(AfterDo); + DoCond->getTerminator()->eraseFromParent(); + DoCond->eraseFromParent(); + } +} + +void CodeGenFunction::EmitForStmt(const ForStmt &S) { + // FIXME: What do we do if the increment (f.e.) contains a stmt expression, + // which contains a continue/break? + // TODO: We could keep track of whether the loop body contains any + // break/continue statements and not create unnecessary blocks (like + // "afterfor" for a condless loop) if it doesn't. + + // Evaluate the first part before the loop. + if (S.getInit()) + EmitStmt(S.getInit()); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = new llvm::BasicBlock("forcond"); + llvm::BasicBlock *AfterFor = new llvm::BasicBlock("afterfor"); + + EmitBlock(CondBlock); + + // Evaluate the condition if present. If not, treat it as a non-zero-constant + // according to 6.8.5.3p2, aka, true. + if (S.getCond()) { + // C99 6.8.5p2/p4: The first substatement is executed if the expression + // compares unequal to 0. The condition must be a scalar type. + llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); + + // As long as the condition is true, iterate the loop. + llvm::BasicBlock *ForBody = new llvm::BasicBlock("forbody"); + Builder.CreateCondBr(BoolCondVal, ForBody, AfterFor); + EmitBlock(ForBody); + } else { + // Treat it as a non-zero constant. Don't even create a new block for the + // body, just fall into it. + } + + // If the for loop doesn't have an increment we can just use the + // condition as the continue block. + llvm::BasicBlock *ContinueBlock; + if (S.getInc()) + ContinueBlock = new llvm::BasicBlock("forinc"); + else + ContinueBlock = CondBlock; + + // Store the blocks to use for break and continue. + BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock)); + + // If the condition is true, execute the body of the for stmt. + EmitStmt(S.getBody()); + + BreakContinueStack.pop_back(); + + if (S.getInc()) + EmitBlock(ContinueBlock); + + // If there is an increment, emit it next. + if (S.getInc()) + EmitStmt(S.getInc()); + + // Finally, branch back up to the condition for the next iteration. + Builder.CreateBr(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor); +} + +/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand +/// if the function returns void, or may be missing one if the function returns +/// non-void. Fun stuff :). +void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { + // Emit the result value, even if unused, to evalute the side effects. + const Expr *RV = S.getRetValue(); + + QualType FnRetTy = CurFuncDecl->getType().getCanonicalType(); + FnRetTy = cast<FunctionType>(FnRetTy)->getResultType(); + + if (FnRetTy->isVoidType()) { + // If the function returns void, emit ret void. + Builder.CreateRetVoid(); + } else if (RV == 0) { + // Handle "return;" in a function that returns a value. + const llvm::Type *RetTy = CurFn->getFunctionType()->getReturnType(); + if (RetTy == llvm::Type::VoidTy) + Builder.CreateRetVoid(); // struct return etc. + else + Builder.CreateRet(llvm::UndefValue::get(RetTy)); + } else if (!hasAggregateLLVMType(RV->getType())) { + Builder.CreateRet(EmitScalarExpr(RV)); + } else if (RV->getType()->isComplexType()) { + llvm::Value *SRetPtr = CurFn->arg_begin(); + EmitComplexExprIntoAddr(RV, SRetPtr, false); + } else { + llvm::Value *SRetPtr = CurFn->arg_begin(); + EmitAggExpr(RV, SRetPtr, false); + } + + // Emit a block after the branch so that dead code after a return has some + // place to go. + EmitBlock(new llvm::BasicBlock()); +} + +void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) { + for (const ScopedDecl *Decl = S.getDecl(); Decl; + Decl = Decl->getNextDeclarator()) + EmitDecl(*Decl); +} + +void CodeGenFunction::EmitBreakStmt() { + assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!"); + + llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock; + Builder.CreateBr(Block); + EmitBlock(new llvm::BasicBlock()); +} + +void CodeGenFunction::EmitContinueStmt() { + assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); + + llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock; + Builder.CreateBr(Block); + EmitBlock(new llvm::BasicBlock()); +} + +/// EmitCaseStmtRange - If case statement range is not too big then +/// add multiple cases to switch instruction, one for each value within +/// the range. If range is too big then emit "if" condition check. +void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { + assert (S.getRHS() && "Unexpected RHS value in CaseStmt"); + + const Expr *L = S.getLHS(); + const Expr *R = S.getRHS(); + llvm::ConstantInt *LV = cast<llvm::ConstantInt>(EmitScalarExpr(L)); + llvm::ConstantInt *RV = cast<llvm::ConstantInt>(EmitScalarExpr(R)); + llvm::APInt LHS = LV->getValue(); + const llvm::APInt &RHS = RV->getValue(); + + llvm::APInt Range = RHS - LHS; + if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) { + // Range is small enough to add multiple switch instruction cases. + StartBlock("sw.bb"); + llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); + SwitchInsn->addCase(LV, CaseDest); + LHS++; + while (LHS != RHS) { + SwitchInsn->addCase(llvm::ConstantInt::get(LHS), CaseDest); + LHS++; + } + SwitchInsn->addCase(RV, CaseDest); + EmitStmt(S.getSubStmt()); + return; + } + + // The range is too big. Emit "if" condition. + llvm::BasicBlock *FalseDest = NULL; + llvm::BasicBlock *CaseDest = new llvm::BasicBlock("sw.bb"); + + // If we have already seen one case statement range for this switch + // instruction then piggy-back otherwise use default block as false + // destination. + if (CaseRangeBlock) + FalseDest = CaseRangeBlock; + else + FalseDest = SwitchInsn->getDefaultDest(); + + // Start new block to hold case statement range check instructions. + StartBlock("case.range"); + CaseRangeBlock = Builder.GetInsertBlock(); + + // Emit range check. + llvm::Value *Diff = + Builder.CreateSub(SwitchInsn->getCondition(), LV, "tmp"); + llvm::Value *Cond = + Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(Range), "tmp"); + Builder.CreateCondBr(Cond, CaseDest, FalseDest); + + // Now emit case statement body. + EmitBlock(CaseDest); + EmitStmt(S.getSubStmt()); +} + +void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { + if (S.getRHS()) { + EmitCaseStmtRange(S); + return; + } + + StartBlock("sw.bb"); + llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); + llvm::APSInt CaseVal(32); + S.getLHS()->isIntegerConstantExpr(CaseVal, getContext()); + llvm::ConstantInt *LV = llvm::ConstantInt::get(CaseVal); + SwitchInsn->addCase(LV, CaseDest); + EmitStmt(S.getSubStmt()); +} + +void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) { + StartBlock("sw.default"); + // Current insert block is the default destination. + SwitchInsn->setSuccessor(0, Builder.GetInsertBlock()); + EmitStmt(S.getSubStmt()); +} + +void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { + llvm::Value *CondV = EmitScalarExpr(S.getCond()); + + // Handle nested switch statements. + llvm::SwitchInst *SavedSwitchInsn = SwitchInsn; + llvm::BasicBlock *SavedCRBlock = CaseRangeBlock; + CaseRangeBlock = NULL; + + // Create basic block to hold stuff that comes after switch statement. + // Initially use it to hold DefaultStmt. + llvm::BasicBlock *NextBlock = new llvm::BasicBlock("after.sw"); + SwitchInsn = Builder.CreateSwitch(CondV, NextBlock); + + // All break statements jump to NextBlock. If BreakContinueStack is non empty + // then reuse last ContinueBlock. + llvm::BasicBlock *ContinueBlock = NULL; + if (!BreakContinueStack.empty()) + ContinueBlock = BreakContinueStack.back().ContinueBlock; + BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock)); + + // Emit switch body. + EmitStmt(S.getBody()); + BreakContinueStack.pop_back(); + + // If one or more case statement range is seen then use CaseRangeBlock + // as the default block. False edge of CaseRangeBlock will lead to + // original default block. + if (CaseRangeBlock) + SwitchInsn->setSuccessor(0, CaseRangeBlock); + + // Prune insert block if it is dummy. + llvm::BasicBlock *BB = Builder.GetInsertBlock(); + if (isDummyBlock(BB)) + BB->eraseFromParent(); + else // Otherwise, branch to continuation. + Builder.CreateBr(NextBlock); + + // Place NextBlock as the new insert point. + CurFn->getBasicBlockList().push_back(NextBlock); + Builder.SetInsertPoint(NextBlock); + SwitchInsn = SavedSwitchInsn; + CaseRangeBlock = SavedCRBlock; +} + +static inline std::string ConvertAsmString(const char *Start, + unsigned NumOperands, + bool IsSimple) +{ + static unsigned AsmCounter = 0; + + AsmCounter++; + + std::string Result; + if (IsSimple) { + while (*Start) { + switch (*Start) { + default: + Result += *Start; + break; + case '$': + Result += "$$"; + break; + } + + Start++; + } + + return Result; + } + + while (*Start) { + switch (*Start) { + default: + Result += *Start; + break; + case '$': + Result += "$$"; + break; + case '%': + // Escaped character + Start++; + if (!*Start) { + // FIXME: This should be caught during Sema. + assert(0 && "Trailing '%' in asm string."); + } + + char EscapedChar = *Start; + if (EscapedChar == '%') { + // Escaped percentage sign. + Result += '%'; + } + else if (EscapedChar == '=') { + // Generate an unique ID. + Result += llvm::utostr(AsmCounter); + } else if (isdigit(EscapedChar)) { + // %n - Assembler operand n + char *End; + + unsigned long n = strtoul(Start, &End, 10); + if (Start == End) { + // FIXME: This should be caught during Sema. + assert(0 && "Missing operand!"); + } else if (n >= NumOperands) { + // FIXME: This should be caught during Sema. + assert(0 && "Operand number out of range!"); + } + + Result += '$' + llvm::utostr(n); + Start = End - 1; + } else if (isalpha(EscapedChar)) { + char *End; + + unsigned long n = strtoul(Start + 1, &End, 10); + if (Start == End) { + // FIXME: This should be caught during Sema. + assert(0 && "Missing operand!"); + } else if (n >= NumOperands) { + // FIXME: This should be caught during Sema. + assert(0 && "Operand number out of range!"); + } + + Result += "${" + llvm::utostr(n) + ':' + EscapedChar + '}'; + Start = End - 1; + } else { + assert(0 && "Unhandled asm escaped character!"); + } + } + Start++; + } + + return Result; +} + +static std::string SimplifyConstraint(const char* Constraint, + TargetInfo &Target) { + std::string Result; + + while (*Constraint) { + switch (*Constraint) { + default: + Result += Target.convertConstraint(*Constraint); + break; + // Ignore these + case '*': + case '?': + case '!': + break; + case 'g': + Result += "imr"; + break; + } + + Constraint++; + } + + return Result; +} + +void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { + std::string AsmString = + ConvertAsmString(std::string(S.getAsmString()->getStrData(), + S.getAsmString()->getByteLength()).c_str(), + S.getNumOutputs() + S.getNumInputs(), S.isSimple()); + + std::string Constraints; + + llvm::Value *ResultAddr = 0; + const llvm::Type *ResultType = llvm::Type::VoidTy; + + std::vector<const llvm::Type*> ArgTypes; + std::vector<llvm::Value*> Args; + + // Keep track of inout constraints. + std::string InOutConstraints; + std::vector<llvm::Value*> InOutArgs; + std::vector<const llvm::Type*> InOutArgTypes; + + for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { + std::string OutputConstraint(S.getOutputConstraint(i)->getStrData(), + S.getOutputConstraint(i)->getByteLength()); + + TargetInfo::ConstraintInfo Info; + bool result = Target.validateOutputConstraint(OutputConstraint.c_str(), + Info); + assert(result && "Failed to parse output constraint"); + + // Simplify the output constraint. + OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target); + + LValue Dest = EmitLValue(S.getOutputExpr(i)); + const llvm::Type *DestValueType = + cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType(); + + // If the first output operand is not a memory dest, we'll + // make it the return value. + if (i == 0 && !(Info & TargetInfo::CI_AllowsMemory) && + DestValueType->isFirstClassType()) { + ResultAddr = Dest.getAddress(); + ResultType = DestValueType; + Constraints += "=" + OutputConstraint; + } else { + ArgTypes.push_back(Dest.getAddress()->getType()); + Args.push_back(Dest.getAddress()); + if (i != 0) + Constraints += ','; + Constraints += "=*"; + Constraints += OutputConstraint; + } + + if (Info & TargetInfo::CI_ReadWrite) { + // FIXME: This code should be shared with the code that handles inputs. + InOutConstraints += ','; + + const Expr *InputExpr = S.getOutputExpr(i); + llvm::Value *Arg; + if ((Info & TargetInfo::CI_AllowsRegister) || + !(Info & TargetInfo::CI_AllowsMemory)) { + if (ConvertType(InputExpr->getType())->isFirstClassType()) { + Arg = EmitScalarExpr(InputExpr); + } else { + assert(0 && "FIXME: Implement passing non first class types as inputs"); + } + } else { + LValue Dest = EmitLValue(InputExpr); + Arg = Dest.getAddress(); + InOutConstraints += '*'; + } + + InOutArgTypes.push_back(Arg->getType()); + InOutArgs.push_back(Arg); + InOutConstraints += OutputConstraint; + } + } + + unsigned NumConstraints = S.getNumOutputs() + S.getNumInputs(); + + for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { + const Expr *InputExpr = S.getInputExpr(i); + + std::string InputConstraint(S.getInputConstraint(i)->getStrData(), + S.getInputConstraint(i)->getByteLength()); + + TargetInfo::ConstraintInfo Info; + bool result = Target.validateInputConstraint(InputConstraint.c_str(), + NumConstraints, + Info); + assert(result && "Failed to parse input constraint"); + + if (i != 0 || S.getNumOutputs() > 0) + Constraints += ','; + + // Simplify the input constraint. + InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target); + + llvm::Value *Arg; + + if ((Info & TargetInfo::CI_AllowsRegister) || + !(Info & TargetInfo::CI_AllowsMemory)) { + if (ConvertType(InputExpr->getType())->isFirstClassType()) { + Arg = EmitScalarExpr(InputExpr); + } else { + assert(0 && "FIXME: Implement passing non first class types as inputs"); + } + } else { + LValue Dest = EmitLValue(InputExpr); + Arg = Dest.getAddress(); + Constraints += '*'; + } + + ArgTypes.push_back(Arg->getType()); + Args.push_back(Arg); + Constraints += InputConstraint; + } + + // Append the "input" part of inout constraints last. + for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) { + ArgTypes.push_back(InOutArgTypes[i]); + Args.push_back(InOutArgs[i]); + } + Constraints += InOutConstraints; + + // Clobbers + for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { + std::string Clobber(S.getClobber(i)->getStrData(), + S.getClobber(i)->getByteLength()); + + Clobber = Target.getNormalizedGCCRegisterName(Clobber.c_str()); + + if (i != 0 || NumConstraints != 0) + Constraints += ','; + + Constraints += "~{"; + Constraints += Clobber; + Constraints += '}'; + } + + // Add machine specific clobbers + if (const char *C = Target.getClobbers()) { + if (!Constraints.empty()) + Constraints += ','; + Constraints += C; + } + + const llvm::FunctionType *FTy = + llvm::FunctionType::get(ResultType, ArgTypes, false); + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, AsmString, Constraints, + S.isVolatile() || S.getNumOutputs() == 0); + llvm::Value *Result = Builder.CreateCall(IA, Args.begin(), Args.end(), ""); + if (ResultAddr) + Builder.CreateStore(Result, ResultAddr); +} diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp new file mode 100644 index 00000000000..49f23f27c34 --- /dev/null +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -0,0 +1,182 @@ +//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This coordinates the per-function state used while generating code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/AST/AST.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Support/CFG.h" +using namespace clang; +using namespace CodeGen; + +CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) + : CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL), + CaseRangeBlock(NULL) {} + +ASTContext &CodeGenFunction::getContext() const { + return CGM.getContext(); +} + + +llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) { + llvm::BasicBlock *&BB = LabelMap[S]; + if (BB) return BB; + + // Create, but don't insert, the new block. + return BB = new llvm::BasicBlock(S->getName()); +} + +llvm::Constant * +CodeGenFunction::GetAddrOfStaticLocalVar(const BlockVarDecl *BVD) { + return cast<llvm::Constant>(LocalDeclMap[BVD]); +} + +const llvm::Type *CodeGenFunction::ConvertType(QualType T) { + return CGM.getTypes().ConvertType(T); +} + +bool CodeGenFunction::hasAggregateLLVMType(QualType T) { + return !T->isRealType() && !T->isPointerType() && !T->isReferenceType() && + !T->isVoidType() && !T->isVectorType() && !T->isFunctionType(); +} + + +void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { + LLVMIntTy = ConvertType(getContext().IntTy); + LLVMPointerWidth = static_cast<unsigned>( + getContext().getTypeSize(getContext().getPointerType(getContext().VoidTy))); + + CurFuncDecl = FD; + CurFn = cast<llvm::Function>(CGM.GetAddrOfFunctionDecl(FD, true)); + assert(CurFn->isDeclaration() && "Function already has body?"); + + // TODO: Set up linkage and many other things. Note, this is a simple + // approximation of what we really want. + if (FD->getAttr<DLLImportAttr>()) + CurFn->setLinkage(llvm::Function::DLLImportLinkage); + else if (FD->getAttr<DLLExportAttr>()) + CurFn->setLinkage(llvm::Function::DLLExportLinkage); + else if (FD->getAttr<WeakAttr>() || FD->isInline()) + CurFn->setLinkage(llvm::Function::WeakLinkage); + else if (FD->getStorageClass() == FunctionDecl::Static) + CurFn->setLinkage(llvm::Function::InternalLinkage); + + if (FD->getAttr<FastCallAttr>()) + CurFn->setCallingConv(llvm::CallingConv::Fast); + + if (const VisibilityAttr *attr = FD->getAttr<VisibilityAttr>()) + CurFn->setVisibility(attr->getVisibility()); + // FIXME: else handle -fvisibility + + + unsigned FuncAttrs = 0; + if (FD->getAttr<NoThrowAttr>()) + FuncAttrs |= llvm::ParamAttr::NoUnwind; + if (FD->getAttr<NoReturnAttr>()) + FuncAttrs |= llvm::ParamAttr::NoReturn; + + if (FuncAttrs) { + llvm::ParamAttrsWithIndex PAWI = + llvm::ParamAttrsWithIndex::get(0, FuncAttrs); + CurFn->setParamAttrs(llvm::PAListPtr::get(&PAWI, 1)); + } + + llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", CurFn); + + // Create a marker to make it easy to insert allocas into the entryblock + // later. Don't create this with the builder, because we don't want it + // folded. + llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty); + AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "allocapt", + EntryBB); + + Builder.SetInsertPoint(EntryBB); + + // Emit allocs for param decls. Give the LLVM Argument nodes names. + llvm::Function::arg_iterator AI = CurFn->arg_begin(); + + // Name the struct return argument. + if (hasAggregateLLVMType(FD->getResultType())) { + AI->setName("agg.result"); + ++AI; + } + + for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) { + assert(AI != CurFn->arg_end() && "Argument mismatch!"); + EmitParmDecl(*FD->getParamDecl(i), AI); + } + + // Emit the function body. + EmitStmt(FD->getBody()); + + // Emit a return for code that falls off the end. If insert point + // is a dummy block with no predecessors then remove the block itself. + llvm::BasicBlock *BB = Builder.GetInsertBlock(); + if (isDummyBlock(BB)) + BB->eraseFromParent(); + else { + // FIXME: if this is C++ main, this should return 0. + if (CurFn->getReturnType() == llvm::Type::VoidTy) + Builder.CreateRetVoid(); + else + Builder.CreateRet(llvm::UndefValue::get(CurFn->getReturnType())); + } + assert(BreakContinueStack.empty() && + "mismatched push/pop in break/continue stack!"); + + // Remove the AllocaInsertPt instruction, which is just a convenience for us. + AllocaInsertPt->eraseFromParent(); + AllocaInsertPt = 0; + + // Verify that the function is well formed. + assert(!verifyFunction(*CurFn)); +} + +/// isDummyBlock - Return true if BB is an empty basic block +/// with no predecessors. +bool CodeGenFunction::isDummyBlock(const llvm::BasicBlock *BB) { + if (BB->empty() && pred_begin(BB) == pred_end(BB)) + return true; + return false; +} + +/// StartBlock - Start new block named N. If insert block is a dummy block +/// then reuse it. +void CodeGenFunction::StartBlock(const char *N) { + llvm::BasicBlock *BB = Builder.GetInsertBlock(); + if (!isDummyBlock(BB)) + EmitBlock(new llvm::BasicBlock(N)); + else + BB->setName(N); +} + +/// getCGRecordLayout - Return record layout info. +const CGRecordLayout *CodeGenFunction::getCGRecordLayout(CodeGenTypes &CGT, + QualType Ty) { + const RecordType *RTy = Ty->getAsRecordType(); + assert (RTy && "Unexpected type. RecordType expected here."); + + return CGT.getCGRecordLayout(RTy->getDecl()); +} + +/// WarnUnsupported - Print out a warning that codegen doesn't support the +/// specified stmt yet. +void CodeGenFunction::WarnUnsupported(const Stmt *S, const char *Type) { + CGM.WarnUnsupported(S, Type); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h new file mode 100644 index 00000000000..509e8296d20 --- /dev/null +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -0,0 +1,486 @@ +//===--- CodeGenFunction.h - Per-Function state for LLVM CodeGen ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the internal per-function state used for llvm translation. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CODEGENFUNCTION_H +#define CLANG_CODEGEN_CODEGENFUNCTION_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/LLVMBuilder.h" +#include <vector> + +namespace llvm { + class Module; +} + +namespace clang { + class ASTContext; + class Decl; + class FunctionDecl; + class TargetInfo; + class QualType; + class FunctionTypeProto; + + class Stmt; + class CompoundStmt; + class LabelStmt; + class GotoStmt; + class IfStmt; + class WhileStmt; + class DoStmt; + class ForStmt; + class ReturnStmt; + class DeclStmt; + class CaseStmt; + class DefaultStmt; + class SwitchStmt; + class AsmStmt; + + class Expr; + class DeclRefExpr; + class StringLiteral; + class IntegerLiteral; + class FloatingLiteral; + class CharacterLiteral; + class TypesCompatibleExpr; + + class ImplicitCastExpr; + class CastExpr; + class CallExpr; + class UnaryOperator; + class BinaryOperator; + class CompoundAssignOperator; + class ArraySubscriptExpr; + class OCUVectorElementExpr; + class ConditionalOperator; + class ChooseExpr; + class PreDefinedExpr; + class ObjCStringLiteral; + class MemberExpr; + + class BlockVarDecl; + class EnumConstantDecl; + class ParmVarDecl; + class FieldDecl; +namespace CodeGen { + class CodeGenModule; + class CodeGenTypes; + class CGRecordLayout; + +/// RValue - This trivial value class is used to represent the result of an +/// expression that is evaluated. It can be one of three things: either a +/// simple LLVM SSA value, a pair of SSA values for complex numbers, or the +/// address of an aggregate value in memory. +class RValue { + llvm::Value *V1, *V2; + // TODO: Encode this into the low bit of pointer for more efficient + // return-by-value. + enum { Scalar, Complex, Aggregate } Flavor; + + // FIXME: Aggregate rvalues need to retain information about whether they are + // volatile or not. +public: + + bool isScalar() const { return Flavor == Scalar; } + bool isComplex() const { return Flavor == Complex; } + bool isAggregate() const { return Flavor == Aggregate; } + + /// getScalar() - Return the Value* of this scalar value. + llvm::Value *getScalarVal() const { + assert(isScalar() && "Not a scalar!"); + return V1; + } + + /// getComplexVal - Return the real/imag components of this complex value. + /// + std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { + return std::pair<llvm::Value *, llvm::Value *>(V1, V2); + } + + /// getAggregateAddr() - Return the Value* of the address of the aggregate. + llvm::Value *getAggregateAddr() const { + assert(isAggregate() && "Not an aggregate!"); + return V1; + } + + static RValue get(llvm::Value *V) { + RValue ER; + ER.V1 = V; + ER.Flavor = Scalar; + return ER; + } + static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { + RValue ER; + ER.V1 = V1; + ER.V2 = V2; + ER.Flavor = Complex; + return ER; + } + static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) { + RValue ER; + ER.V1 = C.first; + ER.V2 = C.second; + ER.Flavor = Complex; + return ER; + } + static RValue getAggregate(llvm::Value *V) { + RValue ER; + ER.V1 = V; + ER.Flavor = Aggregate; + return ER; + } +}; + + +/// LValue - This represents an lvalue references. Because C/C++ allow +/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a +/// bitrange. +class LValue { + // FIXME: Volatility. Restrict? + // alignment? + + enum { + Simple, // This is a normal l-value, use getAddress(). + VectorElt, // This is a vector element l-value (V[i]), use getVector* + BitField, // This is a bitfield l-value, use getBitfield*. + OCUVectorElt // This is an ocu vector subset, use getOCUVectorComp + } LVType; + + llvm::Value *V; + + union { + llvm::Value *VectorIdx; // Index into a vector subscript: V[i] + unsigned VectorElts; // Encoded OCUVector element subset: V.xyx + struct { + unsigned short StartBit; + unsigned short Size; + bool IsSigned; + } BitfieldData; // BitField start bit and size + }; +public: + bool isSimple() const { return LVType == Simple; } + bool isVectorElt() const { return LVType == VectorElt; } + bool isBitfield() const { return LVType == BitField; } + bool isOCUVectorElt() const { return LVType == OCUVectorElt; } + + // simple lvalue + llvm::Value *getAddress() const { assert(isSimple()); return V; } + // vector elt lvalue + llvm::Value *getVectorAddr() const { assert(isVectorElt()); return V; } + llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; } + // ocu vector elements. + llvm::Value *getOCUVectorAddr() const { assert(isOCUVectorElt()); return V; } + unsigned getOCUVectorElts() const { + assert(isOCUVectorElt()); + return VectorElts; + } + // bitfield lvalue + llvm::Value *getBitfieldAddr() const { assert(isBitfield()); return V; } + unsigned short getBitfieldStartBit() const { + assert(isBitfield()); + return BitfieldData.StartBit; + } + unsigned short getBitfieldSize() const { + assert(isBitfield()); + return BitfieldData.Size; + } + bool isBitfieldSigned() const { + assert(isBitfield()); + return BitfieldData.IsSigned; + } + + static LValue MakeAddr(llvm::Value *V) { + LValue R; + R.LVType = Simple; + R.V = V; + return R; + } + + static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx) { + LValue R; + R.LVType = VectorElt; + R.V = Vec; + R.VectorIdx = Idx; + return R; + } + + static LValue MakeOCUVectorElt(llvm::Value *Vec, unsigned Elements) { + LValue R; + R.LVType = OCUVectorElt; + R.V = Vec; + R.VectorElts = Elements; + return R; + } + + static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit, + unsigned short Size, bool IsSigned) { + LValue R; + R.LVType = BitField; + R.V = V; + R.BitfieldData.StartBit = StartBit; + R.BitfieldData.Size = Size; + R.BitfieldData.IsSigned = IsSigned; + return R; + } +}; + +/// CodeGenFunction - This class organizes the per-function state that is used +/// while generating LLVM code. +class CodeGenFunction { +public: + CodeGenModule &CGM; // Per-module state. + TargetInfo &Target; + + typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy; + llvm::LLVMFoldingBuilder Builder; + + const FunctionDecl *CurFuncDecl; + llvm::Function *CurFn; + + /// AllocaInsertPoint - This is an instruction in the entry block before which + /// we prefer to insert allocas. + llvm::Instruction *AllocaInsertPt; + + const llvm::Type *LLVMIntTy; + uint32_t LLVMPointerWidth; + +private: + /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C + /// decls. + llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; + + /// LabelMap - This keeps track of the LLVM basic block for each C label. + llvm::DenseMap<const LabelStmt*, llvm::BasicBlock*> LabelMap; + + // BreakContinueStack - This keeps track of where break and continue + // statements should jump to. + struct BreakContinue { + BreakContinue(llvm::BasicBlock *bb, llvm::BasicBlock *cb) + : BreakBlock(bb), ContinueBlock(cb) {} + + llvm::BasicBlock *BreakBlock; + llvm::BasicBlock *ContinueBlock; + }; + llvm::SmallVector<BreakContinue, 8> BreakContinueStack; + + /// SwitchInsn - This is nearest current switch instruction. It is null if + /// if current context is not in a switch. + llvm::SwitchInst *SwitchInsn; + + /// CaseRangeBlock - This block holds if condition check for last case + /// statement range in current switch instruction. + llvm::BasicBlock *CaseRangeBlock; + +public: + CodeGenFunction(CodeGenModule &cgm); + + ASTContext &getContext() const; + + void GenerateCode(const FunctionDecl *FD); + + const llvm::Type *ConvertType(QualType T); + + /// hasAggregateLLVMType - Return true if the specified AST type will map into + /// an aggregate LLVM type or is void. + static bool hasAggregateLLVMType(QualType T); + + /// getBasicBlockForLabel - Return the LLVM basicblock that the specified + /// label maps to. + llvm::BasicBlock *getBasicBlockForLabel(const LabelStmt *S); + + + void EmitBlock(llvm::BasicBlock *BB); + + /// WarnUnsupported - Print out a warning that codegen doesn't support the + /// specified stmt yet. + void WarnUnsupported(const Stmt *S, const char *Type); + + //===--------------------------------------------------------------------===// + // Helpers + //===--------------------------------------------------------------------===// + + /// CreateTempAlloca - This creates a alloca and inserts it into the entry + /// block. + llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty, + const char *Name = "tmp"); + + /// EvaluateExprAsBool - Perform the usual unary conversions on the specified + /// expression and compare the result against zero, returning an Int1Ty value. + llvm::Value *EvaluateExprAsBool(const Expr *E); + + /// EmitAnyExpr - Emit code to compute the specified expression which can have + /// any type. The result is returned as an RValue struct. If this is an + /// aggregate expression, the aggloc/agglocvolatile arguments indicate where + /// the result should be returned. + RValue EmitAnyExpr(const Expr *E, llvm::Value *AggLoc = 0, + bool isAggLocVolatile = false); + + /// isDummyBlock - Return true if BB is an empty basic block + /// with no predecessors. + static bool isDummyBlock(const llvm::BasicBlock *BB); + + /// StartBlock - Start new block named N. If insert block is a dummy block + /// then reuse it. + void StartBlock(const char *N); + + /// getCGRecordLayout - Return record layout info. + const CGRecordLayout *getCGRecordLayout(CodeGenTypes &CGT, QualType RTy); + + /// GetAddrOfStaticLocalVar - Return the address of a static local variable. + llvm::Constant *GetAddrOfStaticLocalVar(const BlockVarDecl *BVD); + //===--------------------------------------------------------------------===// + // Declaration Emission + //===--------------------------------------------------------------------===// + + void EmitDecl(const Decl &D); + void EmitEnumConstantDecl(const EnumConstantDecl &D); + void EmitBlockVarDecl(const BlockVarDecl &D); + void EmitLocalBlockVarDecl(const BlockVarDecl &D); + void EmitStaticBlockVarDecl(const BlockVarDecl &D); + void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg); + + //===--------------------------------------------------------------------===// + // Statement Emission + //===--------------------------------------------------------------------===// + + void EmitStmt(const Stmt *S); + RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false, + llvm::Value *AggLoc = 0, bool isAggVol = false); + void EmitLabelStmt(const LabelStmt &S); + void EmitGotoStmt(const GotoStmt &S); + void EmitIfStmt(const IfStmt &S); + void EmitWhileStmt(const WhileStmt &S); + void EmitDoStmt(const DoStmt &S); + void EmitForStmt(const ForStmt &S); + void EmitReturnStmt(const ReturnStmt &S); + void EmitDeclStmt(const DeclStmt &S); + void EmitBreakStmt(); + void EmitContinueStmt(); + void EmitSwitchStmt(const SwitchStmt &S); + void EmitDefaultStmt(const DefaultStmt &S); + void EmitCaseStmt(const CaseStmt &S); + void EmitCaseStmtRange(const CaseStmt &S); + void EmitAsmStmt(const AsmStmt &S); + + //===--------------------------------------------------------------------===// + // LValue Expression Emission + //===--------------------------------------------------------------------===// + + /// EmitLValue - Emit code to compute a designator that specifies the location + /// of the expression. + /// + /// This can return one of two things: a simple address or a bitfield + /// reference. In either case, the LLVM Value* in the LValue structure is + /// guaranteed to be an LLVM pointer type. + /// + /// If this returns a bitfield reference, nothing about the pointee type of + /// the LLVM value is known: For example, it may not be a pointer to an + /// integer. + /// + /// If this returns a normal address, and if the lvalue's C type is fixed + /// size, this method guarantees that the returned pointer type will point to + /// an LLVM type of the same size of the lvalue's type. If the lvalue has a + /// variable length type, this is not possible. + /// + LValue EmitLValue(const Expr *E); + + /// EmitLoadOfLValue - Given an expression that represents a value lvalue, + /// this method emits the address of the lvalue, then loads the result as an + /// rvalue, returning the rvalue. + RValue EmitLoadOfLValue(LValue V, QualType LVType); + RValue EmitLoadOfOCUElementLValue(LValue V, QualType LVType); + RValue EmitLoadOfBitfieldLValue(LValue LV, QualType ExprType); + + + /// EmitStoreThroughLValue - Store the specified rvalue into the specified + /// lvalue, where both are guaranteed to the have the same type, and that type + /// is 'Ty'. + void EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty); + void EmitStoreThroughOCUComponentLValue(RValue Src, LValue Dst, QualType Ty); + void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, QualType Ty); + + // Note: only availabe for agg return types + LValue EmitCallExprLValue(const CallExpr *E); + + LValue EmitDeclRefLValue(const DeclRefExpr *E); + LValue EmitStringLiteralLValue(const StringLiteral *E); + LValue EmitPreDefinedLValue(const PreDefinedExpr *E); + LValue EmitUnaryOpLValue(const UnaryOperator *E); + LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E); + LValue EmitOCUVectorElementExpr(const OCUVectorElementExpr *E); + LValue EmitMemberExpr(const MemberExpr *E); + + LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field, + bool isUnion); + + //===--------------------------------------------------------------------===// + // Scalar Expression Emission + //===--------------------------------------------------------------------===// + + RValue EmitCallExpr(const CallExpr *E); + RValue EmitCallExpr(Expr *FnExpr, Expr *const *Args, unsigned NumArgs); + RValue EmitCallExpr(llvm::Value *Callee, QualType FnType, + Expr *const *Args, unsigned NumArgs); + RValue EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + + llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + + llvm::Value *EmitShuffleVector(llvm::Value* V1, llvm::Value *V2, ...); + llvm::Value *EmitVector(llvm::Value * const *Vals, unsigned NumVals, + bool isSplat = false); + + llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E); + + //===--------------------------------------------------------------------===// + // Expression Emission + //===--------------------------------------------------------------------===// + + // Expressions are broken into three classes: scalar, complex, aggregate. + + /// EmitScalarExpr - Emit the computation of the specified expression of + /// LLVM scalar type, returning the result. + llvm::Value *EmitScalarExpr(const Expr *E); + + /// EmitScalarConversion - Emit a conversion from the specified type to the + /// specified destination type, both of which are LLVM scalar types. + llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy, + QualType DstTy); + + /// EmitComplexToScalarConversion - Emit a conversion from the specified + /// complex type to the specified destination type, where the destination + /// type is an LLVM scalar type. + llvm::Value *EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, + QualType DstTy); + + + /// EmitAggExpr - Emit the computation of the specified expression of + /// aggregate type. The result is computed into DestPtr. Note that if + /// DestPtr is null, the value of the aggregate expression is not needed. + void EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest); + + /// EmitComplexExpr - Emit the computation of the specified expression of + /// complex type, returning the result. + ComplexPairTy EmitComplexExpr(const Expr *E); + + /// EmitComplexExprIntoAddr - Emit the computation of the specified expression + /// of complex type, storing into the specified Value*. + void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr, + bool DestIsVolatile); + /// LoadComplexFromAddr - Load a complex number from the specified address. + ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile); +}; +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp new file mode 100644 index 00000000000..43f399a61f2 --- /dev/null +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -0,0 +1,509 @@ +//===--- CodeGenModule.cpp - Emit LLVM Code from ASTs for a Module --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This coordinates the per-module state used while generating code. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenModule.h" +#include "CodeGenFunction.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Intrinsics.h" +#include <algorithm> +using namespace clang; +using namespace CodeGen; + + +CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO, + llvm::Module &M, const llvm::TargetData &TD, + Diagnostic &diags) + : Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags), + Types(C, M, TD), MemCpyFn(0), MemSetFn(0), CFConstantStringClassRef(0) { + //TODO: Make this selectable at runtime + Runtime = CreateObjCRuntime(M); +} + +CodeGenModule::~CodeGenModule() { + EmitGlobalCtors(); + delete Runtime; +} + +/// WarnUnsupported - Print out a warning that codegen doesn't support the +/// specified stmt yet. +void CodeGenModule::WarnUnsupported(const Stmt *S, const char *Type) { + unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Warning, + "cannot codegen this %0 yet"); + SourceRange Range = S->getSourceRange(); + std::string Msg = Type; + getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID, + &Msg, 1, &Range, 1); +} + +/// WarnUnsupported - Print out a warning that codegen doesn't support the +/// specified decl yet. +void CodeGenModule::WarnUnsupported(const Decl *D, const char *Type) { + unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Warning, + "cannot codegen this %0 yet"); + std::string Msg = Type; + getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID, + &Msg, 1); +} + +/// AddGlobalCtor - Add a function to the list that will be called before +/// main() runs. +void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor) { + // TODO: Type coercion of void()* types. + GlobalCtors.push_back(Ctor); +} + +void CodeGenModule::EmitGlobalCtors() { + // Get the type of @llvm.global_ctors + std::vector<const llvm::Type*> CtorFields; + CtorFields.push_back(llvm::IntegerType::get(32)); + // Constructor function type + std::vector<const llvm::Type*> VoidArgs; + llvm::FunctionType* CtorFuncTy = llvm::FunctionType::get( + llvm::Type::VoidTy, + VoidArgs, + false); + // i32, function type pair + CtorFields.push_back(llvm::PointerType::getUnqual(CtorFuncTy)); + llvm::StructType* CtorStructTy = llvm::StructType::get(CtorFields, false); + // Array of fields + llvm::ArrayType* GlobalCtorsTy = llvm::ArrayType::get(CtorStructTy, + GlobalCtors.size()); + + const std::string GlobalCtorsVar = std::string("llvm.global_ctors"); + // Define the global variable + llvm::GlobalVariable *GlobalCtorsVal = new llvm::GlobalVariable( + GlobalCtorsTy, + false, + llvm::GlobalValue::AppendingLinkage, + (llvm::Constant*)0, + GlobalCtorsVar, + &TheModule); + + // Populate the array + std::vector<llvm::Constant*> CtorValues; + llvm::Constant *MagicNumber = llvm::ConstantInt::get(llvm::IntegerType::Int32Ty, + 65535, + false); + for (std::vector<llvm::Constant*>::iterator I = GlobalCtors.begin(), + E = GlobalCtors.end(); I != E; ++I) { + std::vector<llvm::Constant*> StructValues; + StructValues.push_back(MagicNumber); + StructValues.push_back(*I); + + llvm::Constant* CtorEntry = llvm::ConstantStruct::get(CtorStructTy, StructValues); + CtorValues.push_back(CtorEntry); + } + llvm::Constant* CtorArray = llvm::ConstantArray::get(GlobalCtorsTy, CtorValues); + GlobalCtorsVal->setInitializer(CtorArray); + +} + +/// ReplaceMapValuesWith - This is a really slow and bad function that +/// searches for any entries in GlobalDeclMap that point to OldVal, changing +/// them to point to NewVal. This is badbadbad, FIXME! +void CodeGenModule::ReplaceMapValuesWith(llvm::Constant *OldVal, + llvm::Constant *NewVal) { + for (llvm::DenseMap<const Decl*, llvm::Constant*>::iterator + I = GlobalDeclMap.begin(), E = GlobalDeclMap.end(); I != E; ++I) + if (I->second == OldVal) I->second = NewVal; +} + + +llvm::Constant *CodeGenModule::GetAddrOfFunctionDecl(const FunctionDecl *D, + bool isDefinition) { + // See if it is already in the map. If so, just return it. + llvm::Constant *&Entry = GlobalDeclMap[D]; + if (Entry) return Entry; + + const llvm::Type *Ty = getTypes().ConvertType(D->getType()); + + // Check to see if the function already exists. + llvm::Function *F = getModule().getFunction(D->getName()); + const llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty); + + // If it doesn't already exist, just create and return an entry. + if (F == 0) { + // FIXME: param attributes for sext/zext etc. + F = new llvm::Function(FTy, llvm::Function::ExternalLinkage, D->getName(), + &getModule()); + + // Set the appropriate calling convention for the Function. + if (D->getAttr<FastCallAttr>()) + F->setCallingConv(llvm::CallingConv::Fast); + return Entry = F; + } + + // If the pointer type matches, just return it. + llvm::Type *PFTy = llvm::PointerType::getUnqual(Ty); + if (PFTy == F->getType()) return Entry = F; + + // If this isn't a definition, just return it casted to the right type. + if (!isDefinition) + return Entry = llvm::ConstantExpr::getBitCast(F, PFTy); + + // Otherwise, we have a definition after a prototype with the wrong type. + // F is the Function* for the one with the wrong type, we must make a new + // Function* and update everything that used F (a declaration) with the new + // Function* (which will be a definition). + // + // This happens if there is a prototype for a function (e.g. "int f()") and + // then a definition of a different type (e.g. "int f(int x)"). Start by + // making a new function of the correct type, RAUW, then steal the name. + llvm::Function *NewFn = new llvm::Function(FTy, + llvm::Function::ExternalLinkage, + "", &getModule()); + NewFn->takeName(F); + + // Replace uses of F with the Function we will endow with a body. + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(NewFn, F->getType()); + F->replaceAllUsesWith(NewPtrForOldDecl); + + // FIXME: Update the globaldeclmap for the previous decl of this name. We + // really want a way to walk all of these, but we don't have it yet. This + // is incredibly slow! + ReplaceMapValuesWith(F, NewPtrForOldDecl); + + // Ok, delete the old function now, which is dead. + assert(F->isDeclaration() && "Shouldn't replace non-declaration"); + F->eraseFromParent(); + + // Return the new function which has the right type. + return Entry = NewFn; +} + +static bool IsZeroElementArray(const llvm::Type *Ty) { + if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(Ty)) + return ATy->getNumElements() == 0; + return false; +} + +llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, + bool isDefinition) { + assert(D->hasGlobalStorage() && "Not a global variable"); + + // See if it is already in the map. + llvm::Constant *&Entry = GlobalDeclMap[D]; + if (Entry) return Entry; + + QualType ASTTy = D->getType(); + const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy); + + // Check to see if the global already exists. + llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true); + + // If it doesn't already exist, just create and return an entry. + if (GV == 0) { + return Entry = new llvm::GlobalVariable(Ty, false, + llvm::GlobalValue::ExternalLinkage, + 0, D->getName(), &getModule(), 0, + ASTTy.getAddressSpace()); + } + + // If the pointer type matches, just return it. + llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); + if (PTy == GV->getType()) return Entry = GV; + + // If this isn't a definition, just return it casted to the right type. + if (!isDefinition) + return Entry = llvm::ConstantExpr::getBitCast(GV, PTy); + + + // Otherwise, we have a definition after a prototype with the wrong type. + // GV is the GlobalVariable* for the one with the wrong type, we must make a + /// new GlobalVariable* and update everything that used GV (a declaration) + // with the new GlobalVariable* (which will be a definition). + // + // This happens if there is a prototype for a global (e.g. "extern int x[];") + // and then a definition of a different type (e.g. "int x[10];"). Start by + // making a new global of the correct type, RAUW, then steal the name. + llvm::GlobalVariable *NewGV = + new llvm::GlobalVariable(Ty, false, llvm::GlobalValue::ExternalLinkage, + 0, D->getName(), &getModule(), 0, + ASTTy.getAddressSpace()); + NewGV->takeName(GV); + + // Replace uses of GV with the globalvalue we will endow with a body. + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(NewGV, GV->getType()); + GV->replaceAllUsesWith(NewPtrForOldDecl); + + // FIXME: Update the globaldeclmap for the previous decl of this name. We + // really want a way to walk all of these, but we don't have it yet. This + // is incredibly slow! + ReplaceMapValuesWith(GV, NewPtrForOldDecl); + + // Verify that GV was a declaration or something like x[] which turns into + // [0 x type]. + assert((GV->isDeclaration() || + IsZeroElementArray(GV->getType()->getElementType())) && + "Shouldn't replace non-declaration"); + + // Ok, delete the old global now, which is dead. + GV->eraseFromParent(); + + // Return the new global which has the right type. + return Entry = NewGV; +} + + +void CodeGenModule::EmitFunction(const FunctionDecl *FD) { + // If this is not a prototype, emit the body. + if (FD->getBody()) + CodeGenFunction(*this).GenerateCode(FD); +} + +llvm::Constant *CodeGenModule::EmitGlobalInit(const Expr *Expr) { + return EmitConstantExpr(Expr); +} + +void CodeGenModule::EmitGlobalVar(const FileVarDecl *D) { + // If this is just a forward declaration of the variable, don't emit it now, + // allow it to be emitted lazily on its first use. + if (D->getStorageClass() == VarDecl::Extern && D->getInit() == 0) + return; + + // Get the global, forcing it to be a direct reference. + llvm::GlobalVariable *GV = + cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, true)); + + // Convert the initializer, or use zero if appropriate. + llvm::Constant *Init = 0; + if (D->getInit() == 0) { + Init = llvm::Constant::getNullValue(GV->getType()->getElementType()); + } else if (D->getType()->isIntegerType()) { + llvm::APSInt Value(static_cast<uint32_t>( + getContext().getTypeSize(D->getInit()->getType()))); + if (D->getInit()->isIntegerConstantExpr(Value, Context)) + Init = llvm::ConstantInt::get(Value); + } + + if (!Init) + Init = EmitGlobalInit(D->getInit()); + + assert(GV->getType()->getElementType() == Init->getType() && + "Initializer codegen type mismatch!"); + GV->setInitializer(Init); + + if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) + GV->setVisibility(attr->getVisibility()); + // FIXME: else handle -fvisibility + + // Set the llvm linkage type as appropriate. + if (D->getAttr<DLLImportAttr>()) + GV->setLinkage(llvm::Function::DLLImportLinkage); + else if (D->getAttr<DLLExportAttr>()) + GV->setLinkage(llvm::Function::DLLExportLinkage); + else if (D->getAttr<WeakAttr>()) { + GV->setLinkage(llvm::GlobalVariable::WeakLinkage); + + } else { + // FIXME: This isn't right. This should handle common linkage and other + // stuff. + switch (D->getStorageClass()) { + case VarDecl::Auto: + case VarDecl::Register: + assert(0 && "Can't have auto or register globals"); + case VarDecl::None: + if (!D->getInit()) + GV->setLinkage(llvm::GlobalVariable::WeakLinkage); + break; + case VarDecl::Extern: + case VarDecl::PrivateExtern: + // todo: common + break; + case VarDecl::Static: + GV->setLinkage(llvm::GlobalVariable::InternalLinkage); + break; + } + } +} + +/// EmitGlobalVarDeclarator - Emit all the global vars attached to the specified +/// declarator chain. +void CodeGenModule::EmitGlobalVarDeclarator(const FileVarDecl *D) { + for (; D; D = cast_or_null<FileVarDecl>(D->getNextDeclarator())) + EmitGlobalVar(D); +} + +void CodeGenModule::UpdateCompletedType(const TagDecl *TD) { + // Make sure that this type is translated. + Types.UpdateCompletedType(TD); +} + + +/// getBuiltinLibFunction +llvm::Function *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) { + if (BuiltinID > BuiltinFunctions.size()) + BuiltinFunctions.resize(BuiltinID); + + // Cache looked up functions. Since builtin id #0 is invalid we don't reserve + // a slot for it. + assert(BuiltinID && "Invalid Builtin ID"); + llvm::Function *&FunctionSlot = BuiltinFunctions[BuiltinID-1]; + if (FunctionSlot) + return FunctionSlot; + + assert(Context.BuiltinInfo.isLibFunction(BuiltinID) && "isn't a lib fn"); + + // Get the name, skip over the __builtin_ prefix. + const char *Name = Context.BuiltinInfo.GetName(BuiltinID)+10; + + // Get the type for the builtin. + QualType Type = Context.BuiltinInfo.GetBuiltinType(BuiltinID, Context); + const llvm::FunctionType *Ty = + cast<llvm::FunctionType>(getTypes().ConvertType(Type)); + + // FIXME: This has a serious problem with code like this: + // void abs() {} + // ... __builtin_abs(x); + // The two versions of abs will collide. The fix is for the builtin to win, + // and for the existing one to be turned into a constantexpr cast of the + // builtin. In the case where the existing one is a static function, it + // should just be renamed. + if (llvm::Function *Existing = getModule().getFunction(Name)) { + if (Existing->getFunctionType() == Ty && Existing->hasExternalLinkage()) + return FunctionSlot = Existing; + assert(Existing == 0 && "FIXME: Name collision"); + } + + // FIXME: param attributes for sext/zext etc. + return FunctionSlot = new llvm::Function(Ty, llvm::Function::ExternalLinkage, + Name, &getModule()); +} + +llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys, + unsigned NumTys) { + return llvm::Intrinsic::getDeclaration(&getModule(), + (llvm::Intrinsic::ID)IID, Tys, NumTys); +} + +llvm::Function *CodeGenModule::getMemCpyFn() { + if (MemCpyFn) return MemCpyFn; + llvm::Intrinsic::ID IID; + switch (Context.Target.getPointerWidth(0)) { + default: assert(0 && "Unknown ptr width"); + case 32: IID = llvm::Intrinsic::memcpy_i32; break; + case 64: IID = llvm::Intrinsic::memcpy_i64; break; + } + return MemCpyFn = getIntrinsic(IID); +} + +llvm::Function *CodeGenModule::getMemSetFn() { + if (MemSetFn) return MemSetFn; + llvm::Intrinsic::ID IID; + switch (Context.Target.getPointerWidth(0)) { + default: assert(0 && "Unknown ptr width"); + case 32: IID = llvm::Intrinsic::memset_i32; break; + case 64: IID = llvm::Intrinsic::memset_i64; break; + } + return MemSetFn = getIntrinsic(IID); +} + +llvm::Constant *CodeGenModule:: +GetAddrOfConstantCFString(const std::string &str) { + llvm::StringMapEntry<llvm::Constant *> &Entry = + CFConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]); + + if (Entry.getValue()) + return Entry.getValue(); + + std::vector<llvm::Constant*> Fields; + + if (!CFConstantStringClassRef) { + const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); + Ty = llvm::ArrayType::get(Ty, 0); + + CFConstantStringClassRef = + new llvm::GlobalVariable(Ty, false, + llvm::GlobalVariable::ExternalLinkage, 0, + "__CFConstantStringClassReference", + &getModule()); + } + + // Class pointer. + llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty); + llvm::Constant *Zeros[] = { Zero, Zero }; + llvm::Constant *C = + llvm::ConstantExpr::getGetElementPtr(CFConstantStringClassRef, Zeros, 2); + Fields.push_back(C); + + // Flags. + const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); + Fields.push_back(llvm::ConstantInt::get(Ty, 1992)); + + // String pointer. + C = llvm::ConstantArray::get(str); + C = new llvm::GlobalVariable(C->getType(), true, + llvm::GlobalValue::InternalLinkage, + C, ".str", &getModule()); + + C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2); + Fields.push_back(C); + + // String length. + Ty = getTypes().ConvertType(getContext().LongTy); + Fields.push_back(llvm::ConstantInt::get(Ty, str.length())); + + // The struct. + Ty = getTypes().ConvertType(getContext().getCFConstantStringType()); + C = llvm::ConstantStruct::get(cast<llvm::StructType>(Ty), Fields); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(C->getType(), true, + llvm::GlobalVariable::InternalLinkage, + C, "", &getModule()); + GV->setSection("__DATA,__cfstring"); + Entry.setValue(GV); + return GV; +} + +/// GenerateWritableString -- Creates storage for a string literal. +static llvm::Constant *GenerateStringLiteral(const std::string &str, + bool constant, + CodeGenModule &CGM) { + // Create Constant for this string literal + llvm::Constant *C=llvm::ConstantArray::get(str); + + // Create a global variable for this string + C = new llvm::GlobalVariable(C->getType(), constant, + llvm::GlobalValue::InternalLinkage, + C, ".str", &CGM.getModule()); + return C; +} + +/// CodeGenModule::GetAddrOfConstantString -- returns a pointer to the character +/// array containing the literal. The result is pointer to array type. +llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) { + // Don't share any string literals if writable-strings is turned on. + if (Features.WritableStrings) + return GenerateStringLiteral(str, false, *this); + + llvm::StringMapEntry<llvm::Constant *> &Entry = + ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]); + + if (Entry.getValue()) + return Entry.getValue(); + + // Create a global variable for this. + llvm::Constant *C = GenerateStringLiteral(str, true, *this); + Entry.setValue(C); + return C; +} diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h new file mode 100644 index 00000000000..cbea09fd3ec --- /dev/null +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -0,0 +1,129 @@ +//===--- CodeGenModule.h - Per-Module state for LLVM CodeGen --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the internal per-translation-unit state used for llvm translation. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CODEGENMODULE_H +#define CLANG_CODEGEN_CODEGENMODULE_H + +#include "CodeGenTypes.h" +#include "CGObjCRuntime.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" + +namespace llvm { + class Module; + class Constant; + class Function; + class GlobalVariable; + class TargetData; +} + +namespace clang { + class ASTContext; + class FunctionDecl; + class Decl; + class Expr; + class Stmt; + class ValueDecl; + class VarDecl; + class TypeDecl; + class FileVarDecl; + struct LangOptions; + class Diagnostic; + +namespace CodeGen { + + class CodeGenFunction; + +/// CodeGenModule - This class organizes the cross-module state that is used +/// while generating LLVM code. +class CodeGenModule { + ASTContext &Context; + const LangOptions &Features; + llvm::Module &TheModule; + const llvm::TargetData &TheTargetData; + Diagnostic &Diags; + CodeGenTypes Types; + CGObjCRuntime *Runtime; + + llvm::Function *MemCpyFn; + llvm::Function *MemSetFn; + llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap; + std::vector<llvm::Constant*> GlobalCtors; + + llvm::StringMap<llvm::Constant*> CFConstantStringMap; + llvm::StringMap<llvm::Constant*> ConstantStringMap; + llvm::Constant *CFConstantStringClassRef; + + std::vector<llvm::Function *> BuiltinFunctions; +public: + CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M, + const llvm::TargetData &TD, Diagnostic &Diags); + ~CodeGenModule(); + + CGObjCRuntime *getObjCRuntime() { return Runtime; } + ASTContext &getContext() const { return Context; } + const LangOptions &getLangOptions() const { return Features; } + llvm::Module &getModule() const { return TheModule; } + CodeGenTypes &getTypes() { return Types; } + Diagnostic &getDiags() const { return Diags; } + const llvm::TargetData &getTargetData() const { return TheTargetData; } + + llvm::Constant *GetAddrOfFunctionDecl(const FunctionDecl *D, + bool isDefinition); + llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D, bool isDefinition); + + + /// getBuiltinLibFunction - Given a builtin id for a function like + /// "__builtin_fabsf", return a Function* for "fabsf". + /// + llvm::Function *getBuiltinLibFunction(unsigned BuiltinID); + llvm::Constant *GetAddrOfConstantCFString(const std::string& str); + + /// GetAddrOfConstantString -- returns a pointer to the character + /// array containing the literal. The result is pointer to array type. + llvm::Constant *GetAddrOfConstantString(const std::string& str); + llvm::Function *getMemCpyFn(); + llvm::Function *getMemSetFn(); + llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0, + unsigned NumTys = 0); + + void AddGlobalCtor(llvm::Function * Ctor); + void EmitGlobalCtors(void); + + void EmitFunction(const FunctionDecl *FD); + void EmitGlobalVar(const FileVarDecl *D); + void EmitGlobalVarDeclarator(const FileVarDecl *D); + void UpdateCompletedType(const TagDecl *D); + llvm::Constant *EmitGlobalInit(const Expr *E); + llvm::Constant *EmitConstantExpr(const Expr *E, CodeGenFunction *CGF = 0); + + /// WarnUnsupported - Print out a warning that codegen doesn't support the + /// specified stmt yet. + + void WarnUnsupported(const Stmt *S, const char *Type); + + /// WarnUnsupported - Print out a warning that codegen doesn't support the + /// specified decl yet. + void WarnUnsupported(const Decl *D, const char *Type); + +private: + /// ReplaceMapValuesWith - This is a really slow and bad function that + /// searches for any entries in GlobalDeclMap that point to OldVal, changing + /// them to point to NewVal. This is badbadbad, FIXME! + void ReplaceMapValuesWith(llvm::Constant *OldVal, llvm::Constant *NewVal); + +}; +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp new file mode 100644 index 00000000000..9a669e87056 --- /dev/null +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -0,0 +1,580 @@ +//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the code that handles AST -> LLVM type lowering. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenTypes.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/AST/AST.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetData.h" + +using namespace clang; +using namespace CodeGen; + +namespace { + /// RecordOrganizer - This helper class, used by CGRecordLayout, layouts + /// structs and unions. It manages transient information used during layout. + /// FIXME : Handle field aligments. Handle packed structs. + class RecordOrganizer { + public: + explicit RecordOrganizer(CodeGenTypes &Types) : + CGT(Types), STy(NULL), llvmFieldNo(0), Cursor(0), + llvmSize(0) {} + + /// addField - Add new field. + void addField(const FieldDecl *FD); + + /// addLLVMField - Add llvm struct field that corresponds to llvm type Ty. + /// Increment field count. + void addLLVMField(const llvm::Type *Ty, bool isPaddingField = false); + + /// addPaddingFields - Current cursor is not suitable place to add next + /// field. Add required padding fields. + void addPaddingFields(unsigned WaterMark); + + /// layoutStructFields - Do the actual work and lay out all fields. Create + /// corresponding llvm struct type. This should be invoked only after + /// all fields are added. + void layoutStructFields(const ASTRecordLayout &RL); + + /// layoutUnionFields - Do the actual work and lay out all fields. Create + /// corresponding llvm struct type. This should be invoked only after + /// all fields are added. + void layoutUnionFields(); + + /// getLLVMType - Return associated llvm struct type. This may be NULL + /// if fields are not laid out. + llvm::Type *getLLVMType() const { + return STy; + } + + /// placeBitField - Find a place for FD, which is a bit-field. + void placeBitField(const FieldDecl *FD); + + llvm::SmallSet<unsigned, 8> &getPaddingFields() { + return PaddingFields; + } + + private: + CodeGenTypes &CGT; + llvm::Type *STy; + unsigned llvmFieldNo; + uint64_t Cursor; + uint64_t llvmSize; + llvm::SmallVector<const FieldDecl *, 8> FieldDecls; + std::vector<const llvm::Type*> LLVMFields; + llvm::SmallSet<unsigned, 8> PaddingFields; + }; +} + +CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M, + const llvm::TargetData &TD) + : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD) { +} + +CodeGenTypes::~CodeGenTypes() { + for(llvm::DenseMap<const TagDecl *, CGRecordLayout *>::iterator + I = CGRecordLayouts.begin(), E = CGRecordLayouts.end(); + I != E; ++I) + delete I->second; + CGRecordLayouts.clear(); +} + +/// ConvertType - Convert the specified type to its LLVM form. +const llvm::Type *CodeGenTypes::ConvertType(QualType T) { + // See if type is already cached. + llvm::DenseMap<Type *, llvm::PATypeHolder>::iterator + I = TypeCache.find(T.getCanonicalType().getTypePtr()); + // If type is found in map and this is not a definition for a opaque + // place holder type then use it. Otherwise, convert type T. + if (I != TypeCache.end()) + return I->second.get(); + + const llvm::Type *ResultType = ConvertNewType(T); + TypeCache.insert(std::make_pair(T.getCanonicalType().getTypePtr(), + llvm::PATypeHolder(ResultType))); + return ResultType; +} + +/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from +/// ConvertType in that it is used to convert to the memory representation for +/// a type. For example, the scalar representation for _Bool is i1, but the +/// memory representation is usually i8 or i32, depending on the target. +const llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) { + const llvm::Type *R = ConvertType(T); + + // If this is a non-bool type, don't map it. + if (R != llvm::Type::Int1Ty) + return R; + + // Otherwise, return an integer of the target-specified size. + return llvm::IntegerType::get((unsigned)Context.getTypeSize(T)); + +} + +/// UpdateCompletedType - When we find the full definition for a TagDecl, +/// replace the 'opaque' type we previously made for it if applicable. +void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { + llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI = + TagDeclTypes.find(TD); + if (TDTI == TagDeclTypes.end()) return; + + // Remember the opaque LLVM type for this tagdecl. + llvm::PATypeHolder OpaqueHolder = TDTI->second; + assert(isa<llvm::OpaqueType>(OpaqueHolder.get()) && + "Updating compilation of an already non-opaque type?"); + + // Remove it from TagDeclTypes so that it will be regenerated. + TagDeclTypes.erase(TDTI); + + // Generate the new type. + const llvm::Type *NT = ConvertTagDeclType(TD); + + // Refine the old opaque type to its new definition. + cast<llvm::OpaqueType>(OpaqueHolder.get())->refineAbstractTypeTo(NT); +} + + + +const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { + const clang::Type &Ty = *T.getCanonicalType(); + + switch (Ty.getTypeClass()) { + case Type::TypeName: // typedef isn't canonical. + case Type::TypeOfExp: // typeof isn't canonical. + case Type::TypeOfTyp: // typeof isn't canonical. + assert(0 && "Non-canonical type, shouldn't happen"); + case Type::Builtin: { + switch (cast<BuiltinType>(Ty).getKind()) { + case BuiltinType::Void: + // LLVM void type can only be used as the result of a function call. Just + // map to the same as char. + return llvm::IntegerType::get(8); + + case BuiltinType::Bool: + // Note that we always return bool as i1 for use as a scalar type. + return llvm::Type::Int1Ty; + + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::Int: + case BuiltinType::UInt: + case BuiltinType::Long: + case BuiltinType::ULong: + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + return llvm::IntegerType::get( + static_cast<unsigned>(Context.getTypeSize(T))); + + case BuiltinType::Float: return llvm::Type::FloatTy; + case BuiltinType::Double: return llvm::Type::DoubleTy; + case BuiltinType::LongDouble: + // FIXME: mapping long double onto double. + return llvm::Type::DoubleTy; + } + break; + } + case Type::Complex: { + std::vector<const llvm::Type*> Elts; + Elts.push_back(ConvertType(cast<ComplexType>(Ty).getElementType())); + Elts.push_back(Elts[0]); + return llvm::StructType::get(Elts); + } + case Type::Pointer: { + const PointerType &P = cast<PointerType>(Ty); + QualType ETy = P.getPointeeType(); + return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace()); + } + case Type::Reference: { + const ReferenceType &R = cast<ReferenceType>(Ty); + return llvm::PointerType::getUnqual(ConvertType(R.getReferenceeType())); + } + + case Type::VariableArray: { + const VariableArrayType &A = cast<VariableArrayType>(Ty); + assert(A.getIndexTypeQualifier() == 0 && + "FIXME: We only handle trivial array types so far!"); + // VLAs resolve to the innermost element type; this matches + // the return of alloca, and there isn't any obviously better choice. + return ConvertType(A.getElementType()); + } + case Type::IncompleteArray: { + const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty); + assert(A.getIndexTypeQualifier() == 0 && + "FIXME: We only handle trivial array types so far!"); + // int X[] -> [0 x int] + return llvm::ArrayType::get(ConvertType(A.getElementType()), 0); + } + case Type::ConstantArray: { + const ConstantArrayType &A = cast<ConstantArrayType>(Ty); + const llvm::Type *EltTy = ConvertType(A.getElementType()); + return llvm::ArrayType::get(EltTy, A.getSize().getZExtValue()); + } + case Type::OCUVector: + case Type::Vector: { + const VectorType &VT = cast<VectorType>(Ty); + return llvm::VectorType::get(ConvertType(VT.getElementType()), + VT.getNumElements()); + } + case Type::FunctionNoProto: + case Type::FunctionProto: { + const FunctionType &FP = cast<FunctionType>(Ty); + const llvm::Type *ResultType; + + if (FP.getResultType()->isVoidType()) + ResultType = llvm::Type::VoidTy; // Result of function uses llvm void. + else + ResultType = ConvertType(FP.getResultType()); + + // FIXME: Convert argument types. + bool isVarArg; + std::vector<const llvm::Type*> ArgTys; + + // Struct return passes the struct byref. + if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) { + ArgTys.push_back(llvm::PointerType::get(ResultType, + FP.getResultType().getAddressSpace())); + ResultType = llvm::Type::VoidTy; + } + + if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(&FP)) { + DecodeArgumentTypes(*FTP, ArgTys); + isVarArg = FTP->isVariadic(); + } else { + isVarArg = true; + } + + return llvm::FunctionType::get(ResultType, ArgTys, isVarArg); + } + + case Type::ASQual: + return ConvertType(QualType(cast<ASQualType>(Ty).getBaseType(), 0)); + + case Type::ObjCInterface: + assert(0 && "FIXME: add missing functionality here"); + break; + + case Type::ObjCQualifiedInterface: + assert(0 && "FIXME: add missing functionality here"); + break; + + case Type::ObjCQualifiedId: + assert(0 && "FIXME: add missing functionality here"); + break; + + case Type::Tagged: { + const TagDecl *TD = cast<TagType>(Ty).getDecl(); + const llvm::Type *Res = ConvertTagDeclType(TD); + + std::string TypeName(TD->getKindName()); + TypeName += '.'; + + // Name the codegen type after the typedef name + // if there is no tag type name available + if (TD->getIdentifier()) + TypeName += TD->getName(); + else if (const TypedefType *TdT = dyn_cast<TypedefType>(T)) + TypeName += TdT->getDecl()->getName(); + else + TypeName += "anon"; + + TheModule.addTypeName(TypeName, Res); + return Res; + } + } + + // FIXME: implement. + return llvm::OpaqueType::get(); +} + +void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP, + std::vector<const llvm::Type*> &ArgTys) { + for (unsigned i = 0, e = FTP.getNumArgs(); i != e; ++i) { + const llvm::Type *Ty = ConvertType(FTP.getArgType(i)); + if (Ty->isFirstClassType()) + ArgTys.push_back(Ty); + else + // byval arguments are always on the stack, which is addr space #0. + ArgTys.push_back(llvm::PointerType::getUnqual(Ty)); + } +} + +/// ConvertTagDeclType - Lay out a tagged decl type like struct or union or +/// enum. +const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) { + llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI = + TagDeclTypes.find(TD); + + // If we've already compiled this tag type, use the previous definition. + if (TDTI != TagDeclTypes.end()) + return TDTI->second; + + // If this is still a forward definition, just define an opaque type to use + // for this tagged decl. + if (!TD->isDefinition()) { + llvm::Type *ResultType = llvm::OpaqueType::get(); + TagDeclTypes.insert(std::make_pair(TD, ResultType)); + return ResultType; + } + + // Okay, this is a definition of a type. Compile the implementation now. + + if (TD->getKind() == Decl::Enum) { + // Don't bother storing enums in TagDeclTypes. + return ConvertType(cast<EnumDecl>(TD)->getIntegerType()); + } + + // This decl could well be recursive. In this case, insert an opaque + // definition of this type, which the recursive uses will get. We will then + // refine this opaque version later. + + // Create new OpaqueType now for later use in case this is a recursive + // type. This will later be refined to the actual type. + llvm::PATypeHolder ResultHolder = llvm::OpaqueType::get(); + TagDeclTypes.insert(std::make_pair(TD, ResultHolder)); + + const llvm::Type *ResultType; + const RecordDecl *RD = cast<const RecordDecl>(TD); + if (TD->getKind() == Decl::Struct || TD->getKind() == Decl::Class) { + // Layout fields. + RecordOrganizer RO(*this); + for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i) + RO.addField(RD->getMember(i)); + + RO.layoutStructFields(Context.getASTRecordLayout(RD)); + + // Get llvm::StructType. + CGRecordLayouts[TD] = new CGRecordLayout(RO.getLLVMType(), + RO.getPaddingFields()); + ResultType = RO.getLLVMType(); + + } else if (TD->getKind() == Decl::Union) { + // Just use the largest element of the union, breaking ties with the + // highest aligned member. + if (RD->getNumMembers() != 0) { + RecordOrganizer RO(*this); + for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i) + RO.addField(RD->getMember(i)); + + RO.layoutUnionFields(); + + // Get llvm::StructType. + CGRecordLayouts[TD] = new CGRecordLayout(RO.getLLVMType(), + RO.getPaddingFields()); + ResultType = RO.getLLVMType(); + } else { + ResultType = llvm::StructType::get(std::vector<const llvm::Type*>()); + } + } else { + assert(0 && "FIXME: Unknown tag decl kind!"); + } + + // Refine our Opaque type to ResultType. This can invalidate ResultType, so + // make sure to read the result out of the holder. + cast<llvm::OpaqueType>(ResultHolder.get()) + ->refineAbstractTypeTo(ResultType); + + return ResultHolder.get(); +} + +/// getLLVMFieldNo - Return llvm::StructType element number +/// that corresponds to the field FD. +unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) { + llvm::DenseMap<const FieldDecl *, unsigned>::iterator + I = FieldInfo.find(FD); + assert (I != FieldInfo.end() && "Unable to find field info"); + return I->second; +} + +/// addFieldInfo - Assign field number to field FD. +void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) { + FieldInfo[FD] = No; +} + +/// getBitFieldInfo - Return the BitFieldInfo that corresponds to the field FD. +CodeGenTypes::BitFieldInfo CodeGenTypes::getBitFieldInfo(const FieldDecl *FD) { + llvm::DenseMap<const FieldDecl *, BitFieldInfo>::iterator + I = BitFields.find(FD); + assert (I != BitFields.end() && "Unable to find bitfield info"); + return I->second; +} + +/// addBitFieldInfo - Assign a start bit and a size to field FD. +void CodeGenTypes::addBitFieldInfo(const FieldDecl *FD, unsigned Begin, + unsigned Size) { + BitFields.insert(std::make_pair(FD, BitFieldInfo(Begin, Size))); +} + +/// getCGRecordLayout - Return record layout info for the given llvm::Type. +const CGRecordLayout * +CodeGenTypes::getCGRecordLayout(const TagDecl *TD) const { + llvm::DenseMap<const TagDecl*, CGRecordLayout *>::iterator I + = CGRecordLayouts.find(TD); + assert (I != CGRecordLayouts.end() + && "Unable to find record layout information for type"); + return I->second; +} + +/// addField - Add new field. +void RecordOrganizer::addField(const FieldDecl *FD) { + assert (!STy && "Record fields are already laid out"); + FieldDecls.push_back(FD); +} + +/// layoutStructFields - Do the actual work and lay out all fields. Create +/// corresponding llvm struct type. This should be invoked only after +/// all fields are added. +/// FIXME : At the moment assume +/// - one to one mapping between AST FieldDecls and +/// llvm::StructType elements. +/// - Ignore bit fields +/// - Ignore field aligments +/// - Ignore packed structs +void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) { + // FIXME : Use SmallVector + llvmSize = 0; + llvmFieldNo = 0; + Cursor = 0; + LLVMFields.clear(); + + for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(), + E = FieldDecls.end(); I != E; ++I) { + const FieldDecl *FD = *I; + + if (FD->isBitField()) + placeBitField(FD); + else { + const llvm::Type *Ty = CGT.ConvertType(FD->getType()); + addLLVMField(Ty); + CGT.addFieldInfo(FD, llvmFieldNo - 1); + Cursor = llvmSize; + } + } + + unsigned StructAlign = RL.getAlignment(); + if (llvmSize % StructAlign) { + unsigned StructPadding = StructAlign - (llvmSize % StructAlign); + addPaddingFields(llvmSize + StructPadding); + } + + STy = llvm::StructType::get(LLVMFields); +} + +/// addPaddingFields - Current cursor is not suitable place to add next field. +/// Add required padding fields. +void RecordOrganizer::addPaddingFields(unsigned WaterMark) { + assert(WaterMark >= llvmSize && "Invalid padding Field"); + unsigned RequiredBits = WaterMark - llvmSize; + unsigned RequiredBytes = (RequiredBits + 7) / 8; + for (unsigned i = 0; i != RequiredBytes; ++i) + addLLVMField(llvm::Type::Int8Ty, true); +} + +/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty. +/// Increment field count. +void RecordOrganizer::addLLVMField(const llvm::Type *Ty, bool isPaddingField) { + + unsigned AlignmentInBits = CGT.getTargetData().getABITypeAlignment(Ty) * 8; + if (llvmSize % AlignmentInBits) { + // At the moment, insert padding fields even if target specific llvm + // type alignment enforces implict padding fields for FD. Later on, + // optimize llvm fields by removing implicit padding fields and + // combining consequetive padding fields. + unsigned Padding = AlignmentInBits - (llvmSize % AlignmentInBits); + addPaddingFields(llvmSize + Padding); + } + + unsigned TySize = CGT.getTargetData().getABITypeSizeInBits(Ty); + llvmSize += TySize; + if (isPaddingField) + PaddingFields.insert(llvmFieldNo); + LLVMFields.push_back(Ty); + ++llvmFieldNo; +} + +/// layoutUnionFields - Do the actual work and lay out all fields. Create +/// corresponding llvm struct type. This should be invoked only after +/// all fields are added. +void RecordOrganizer::layoutUnionFields() { + + unsigned PrimaryEltNo = 0; + std::pair<uint64_t, unsigned> PrimaryElt = + CGT.getContext().getTypeInfo(FieldDecls[0]->getType()); + CGT.addFieldInfo(FieldDecls[0], 0); + + unsigned Size = FieldDecls.size(); + for(unsigned i = 1; i != Size; ++i) { + const FieldDecl *FD = FieldDecls[i]; + assert (!FD->isBitField() && "Bit fields are not yet supported"); + std::pair<uint64_t, unsigned> EltInfo = + CGT.getContext().getTypeInfo(FD->getType()); + + // Use largest element, breaking ties with the hightest aligned member. + if (EltInfo.first > PrimaryElt.first || + (EltInfo.first == PrimaryElt.first && + EltInfo.second > PrimaryElt.second)) { + PrimaryElt = EltInfo; + PrimaryEltNo = i; + } + + // In union, each field gets first slot. + CGT.addFieldInfo(FD, 0); + } + + std::vector<const llvm::Type*> Fields; + const llvm::Type *Ty = CGT.ConvertType(FieldDecls[PrimaryEltNo]->getType()); + Fields.push_back(Ty); + STy = llvm::StructType::get(Fields); +} + +/// placeBitField - Find a place for FD, which is a bit-field. +/// This function searches for the last aligned field. If the bit-field fits in +/// it, it is reused. Otherwise, the bit-field is placed in a new field. +void RecordOrganizer::placeBitField(const FieldDecl *FD) { + + assert (FD->isBitField() && "FD is not a bit-field"); + Expr *BitWidth = FD->getBitWidth(); + llvm::APSInt FieldSize(32); + bool isBitField = + BitWidth->isIntegerConstantExpr(FieldSize, CGT.getContext()); + assert (isBitField && "Invalid BitField size expression"); + uint64_t BitFieldSize = FieldSize.getZExtValue(); + + const llvm::Type *Ty = CGT.ConvertType(FD->getType()); + uint64_t TySize = CGT.getTargetData().getABITypeSizeInBits(Ty); + + unsigned Idx = Cursor / TySize; + unsigned BitsLeft = TySize - (Cursor % TySize); + + if (BitsLeft >= BitFieldSize) { + // The bitfield fits in the last aligned field. + // This is : struct { char a; int CurrentField:10;}; + // where 'CurrentField' shares first field with 'a'. + CGT.addFieldInfo(FD, Idx); + CGT.addBitFieldInfo(FD, TySize - BitsLeft, BitFieldSize); + Cursor += BitFieldSize; + } else { + // Place the bitfield in a new LLVM field. + // This is : struct { char a; short CurrentField:10;}; + // where 'CurrentField' needs a new llvm field. + CGT.addFieldInfo(FD, Idx + 1); + CGT.addBitFieldInfo(FD, 0, BitFieldSize); + Cursor = (Idx + 1) * TySize + BitFieldSize; + } + if (Cursor > llvmSize) + addPaddingFields(Cursor); +} diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h new file mode 100644 index 00000000000..08a2467106a --- /dev/null +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -0,0 +1,165 @@ +//===--- CodeGenTypes.h - Type translation for LLVM CodeGen -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the code that handles AST -> LLVM type lowering. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CODEGENTYPES_H +#define CLANG_CODEGEN_CODEGENTYPES_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include <vector> + +namespace llvm { + class Module; + class Type; + class PATypeHolder; + class TargetData; +} + +namespace clang { + class ASTContext; + class TagDecl; + class TargetInfo; + class QualType; + class Type; + class FunctionTypeProto; + class FieldDecl; + class RecordDecl; + +namespace CodeGen { + class CodeGenTypes; + + /// CGRecordLayout - This class handles struct and union layout info while + /// lowering AST types to LLVM types. + class CGRecordLayout { + CGRecordLayout(); // DO NOT IMPLEMENT + public: + CGRecordLayout(llvm::Type *T, llvm::SmallSet<unsigned, 8> &PF) + : STy(T), PaddingFields(PF) { + // FIXME : Collect info about fields that requires adjustments + // (i.e. fields that do not directly map to llvm struct fields.) + } + + /// getLLVMType - Return llvm type associated with this record. + llvm::Type *getLLVMType() const { + return STy; + } + + bool isPaddingField(unsigned No) const { + return PaddingFields.count(No) != 0; + } + + unsigned getNumPaddingFields() { + return PaddingFields.size(); + } + + private: + llvm::Type *STy; + llvm::SmallSet<unsigned, 8> PaddingFields; + }; + +/// CodeGenTypes - This class organizes the cross-module state that is used +/// while lowering AST types to LLVM types. +class CodeGenTypes { + ASTContext &Context; + TargetInfo &Target; + llvm::Module& TheModule; + const llvm::TargetData& TheTargetData; + + llvm::DenseMap<const TagDecl*, llvm::PATypeHolder> TagDeclTypes; + + /// CGRecordLayouts - This maps llvm struct type with corresponding + /// record layout info. + /// FIXME : If CGRecordLayout is less than 16 bytes then use + /// inline it in the map. + llvm::DenseMap<const TagDecl*, CGRecordLayout *> CGRecordLayouts; + + /// FieldInfo - This maps struct field with corresponding llvm struct type + /// field no. This info is populated by record organizer. + llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo; + +public: + class BitFieldInfo { + public: + explicit BitFieldInfo(unsigned short B, unsigned short S) + : Begin(B), Size(S) {} + + unsigned short Begin; + unsigned short Size; + }; + +private: + llvm::DenseMap<const FieldDecl *, BitFieldInfo> BitFields; + + /// TypeCache - This map keeps cache of llvm::Types (through PATypeHolder) + /// and maps llvm::Types to corresponding clang::Type. llvm::PATypeHolder is + /// used instead of llvm::Type because it allows us to bypass potential + /// dangling type pointers due to type refinement on llvm side. + llvm::DenseMap<Type *, llvm::PATypeHolder> TypeCache; + + /// ConvertNewType - Convert type T into a llvm::Type. Do not use this + /// method directly because it does not do any type caching. This method + /// is available only for ConvertType(). CovertType() is preferred + /// interface to convert type T into a llvm::Type. + const llvm::Type *ConvertNewType(QualType T); +public: + CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD); + ~CodeGenTypes(); + + const llvm::TargetData &getTargetData() const { return TheTargetData; } + TargetInfo &getTarget() const { return Target; } + ASTContext &getContext() const { return Context; } + + /// ConvertType - Convert type T into a llvm::Type. + const llvm::Type *ConvertType(QualType T); + + /// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from + /// ConvertType in that it is used to convert to the memory representation for + /// a type. For example, the scalar representation for _Bool is i1, but the + /// memory representation is usually i8 or i32, depending on the target. + const llvm::Type *ConvertTypeForMem(QualType T); + + + const CGRecordLayout *getCGRecordLayout(const TagDecl*) const; + + /// getLLVMFieldNo - Return llvm::StructType element number + /// that corresponds to the field FD. + unsigned getLLVMFieldNo(const FieldDecl *FD); + + + /// UpdateCompletedType - When we find the full definition for a TagDecl, + /// replace the 'opaque' type we previously made for it if applicable. + void UpdateCompletedType(const TagDecl *TD); + +public: // These are internal details of CGT that shouldn't be used externally. + void DecodeArgumentTypes(const FunctionTypeProto &FTP, + std::vector<const llvm::Type*> &ArgTys); + + /// addFieldInfo - Assign field number to field FD. + void addFieldInfo(const FieldDecl *FD, unsigned No); + + /// addBitFieldInfo - Assign a start bit and a size to field FD. + void addBitFieldInfo(const FieldDecl *FD, unsigned Begin, unsigned Size); + + /// getBitFieldInfo - Return the BitFieldInfo that corresponds to the field + /// FD. + BitFieldInfo getBitFieldInfo(const FieldDecl *FD); + + /// ConvertTagDeclType - Lay out a tagged decl type like struct or union or + /// enum. + const llvm::Type *ConvertTagDeclType(const TagDecl *TD); +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang/lib/CodeGen/Makefile b/clang/lib/CodeGen/Makefile new file mode 100644 index 00000000000..4d7828ef67a --- /dev/null +++ b/clang/lib/CodeGen/Makefile @@ -0,0 +1,23 @@ +##===- clang/lib/CodeGen/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This implements the AST -> LLVM code generation library for the +# C-Language front-end. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME := clangCodeGen +BUILD_ARCHIVE = 1 +CXXFLAGS = -fno-rtti + +CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include + +include $(LEVEL)/Makefile.common + diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp new file mode 100644 index 00000000000..06467488a5e --- /dev/null +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -0,0 +1,104 @@ +//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This builds an AST and converts it to LLVM Code. +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGen/ModuleBuilder.h" +#include "CodeGenModule.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// LLVM Emitter + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" + +namespace { + class CodeGenerator : public ASTConsumer { + Diagnostic &Diags; + const llvm::TargetData *TD; + ASTContext *Ctx; + const LangOptions &Features; + protected: + llvm::Module *&M; + CodeGen::CodeGenModule *Builder; + public: + CodeGenerator(Diagnostic &diags, const LangOptions &LO, + llvm::Module *&DestModule) + : Diags(diags), Features(LO), M(DestModule) {} + + ~CodeGenerator() { + delete Builder; + } + + virtual void Initialize(ASTContext &Context) { + Ctx = &Context; + + M->setTargetTriple(Ctx->Target.getTargetTriple()); + M->setDataLayout(Ctx->Target.getTargetDescription()); + TD = new llvm::TargetData(Ctx->Target.getTargetDescription()); + Builder = new CodeGen::CodeGenModule(Context, Features, *M, *TD, Diags); + } + + virtual void HandleTopLevelDecl(Decl *D) { + // If an error occurred, stop code generation, but continue parsing and + // semantic analysis (to ensure all warnings and errors are emitted). + if (Diags.hasErrorOccurred()) + return; + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + Builder->EmitFunction(FD); + } else if (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) { + Builder->EmitGlobalVarDeclarator(FVD); + } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { + if (LSD->getLanguage() == LinkageSpecDecl::lang_cxx) + Builder->WarnUnsupported(LSD, "linkage spec"); + // FIXME: implement C++ linkage, C linkage works mostly by C + // language reuse already. + } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) { + std::string AsmString(AD->getAsmString()->getStrData(), + AD->getAsmString()->getByteLength()); + + const std::string &S = Builder->getModule().getModuleInlineAsm(); + if (S.empty()) + Builder->getModule().setModuleInlineAsm(AsmString); + else + Builder->getModule().setModuleInlineAsm(S + '\n' + AsmString); + } else { + assert(isa<TypeDecl>(D) && "Unknown top level decl"); + // TODO: handle debug info? + } + } + + /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl + /// (e.g. struct, union, enum, class) is completed. This allows the client to + /// hack on the type, which can occur at any point in the file (because these + /// can be defined in declspecs). + virtual void HandleTagDeclDefinition(TagDecl *D) { + Builder->UpdateCompletedType(D); + } + + }; +} + +ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags, + const LangOptions &Features, + llvm::Module *&DestModule) { + return new CodeGenerator(Diags, Features, DestModule); +} + |