diff options
Diffstat (limited to 'CodeGen')
-rw-r--r-- | CodeGen/CGDecl.cpp | 119 | ||||
-rw-r--r-- | CodeGen/CGExpr.cpp | 1211 | ||||
-rw-r--r-- | CodeGen/CGStmt.cpp | 284 | ||||
-rw-r--r-- | CodeGen/CodeGenFunction.cpp | 98 | ||||
-rw-r--r-- | CodeGen/CodeGenFunction.h | 354 | ||||
-rw-r--r-- | CodeGen/CodeGenModule.cpp | 68 | ||||
-rw-r--r-- | CodeGen/CodeGenModule.h | 60 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.cpp | 151 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.h | 47 | ||||
-rw-r--r-- | CodeGen/Makefile | 23 | ||||
-rw-r--r-- | CodeGen/ModuleBuilder.cpp | 39 |
11 files changed, 2454 insertions, 0 deletions
diff --git a/CodeGen/CGDecl.cpp b/CodeGen/CGDecl.cpp new file mode 100644 index 0000000000..822aca3f55 --- /dev/null +++ b/CodeGen/CGDecl.cpp @@ -0,0 +1,119 @@ +//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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 "clang/AST/AST.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::FileVariable: + assert(0 && "Should not see file-scope variables inside a function!"); + case Decl::ParmVariable: + 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::BlockVariable: + 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: + assert(0 && "FIXME: local static vars not implemented yet"); + case VarDecl::Extern: + assert(0 && "FIXME: should call up to codegenmodule"); + default: + assert((D.getStorageClass() == VarDecl::None || + D.getStorageClass() == VarDecl::Auto || + D.getStorageClass() == VarDecl::Register) && + "Unknown storage class"); + return EmitLocalBlockVarDecl(D); + } +} + +/// 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; + + // FIXME: Evaluate initializer. +} + +/// 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/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp new file mode 100644 index 0000000000..936770e42d --- /dev/null +++ b/CodeGen/CGExpr.cpp @@ -0,0 +1,1211 @@ +//===--- CGExpr.cpp - Emit LLVM Code from Expressions ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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" +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 Ty; + RValue Val = EmitExprWithUsualUnaryConversions(E, Ty); + return ConvertScalarValueToBool(Val, Ty); +} + +/// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to +/// load the real and imaginary pieces, returning them as Real/Imag. +void CodeGenFunction::EmitLoadOfComplex(RValue V, + llvm::Value *&Real, llvm::Value *&Imag){ + llvm::Value *Ptr = V.getAggregateAddr(); + + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); + llvm::Value *RealPtr = Builder.CreateGEP(Ptr, Zero, Zero, "realp"); + llvm::Value *ImagPtr = Builder.CreateGEP(Ptr, Zero, One, "imagp"); + + // FIXME: Handle volatility. + Real = Builder.CreateLoad(RealPtr, "real"); + Imag = Builder.CreateLoad(ImagPtr, "imag"); +} + +/// EmitStoreOfComplex - Store the specified real/imag parts into the +/// specified value pointer. +void CodeGenFunction::EmitStoreOfComplex(llvm::Value *Real, llvm::Value *Imag, + llvm::Value *ResPtr) { + llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Constant *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); + llvm::Value *RealPtr = Builder.CreateGEP(ResPtr, Zero, Zero, "real"); + llvm::Value *ImagPtr = Builder.CreateGEP(ResPtr, Zero, One, "imag"); + + // FIXME: Handle volatility. + Builder.CreateStore(Real, RealPtr); + Builder.CreateStore(Imag, ImagPtr); +} + +//===--------------------------------------------------------------------===// +// Conversions +//===--------------------------------------------------------------------===// + +/// EmitConversion - Convert the value specied by Val, whose type is ValTy, to +/// the type specified by DstTy, following the rules of C99 6.3. +RValue CodeGenFunction::EmitConversion(RValue Val, QualType ValTy, + QualType DstTy) { + ValTy = ValTy.getCanonicalType(); + DstTy = DstTy.getCanonicalType(); + if (ValTy == DstTy) return Val; + + // Handle conversions to bool first, they are special: comparisons against 0. + if (const BuiltinType *DestBT = dyn_cast<BuiltinType>(DstTy)) + if (DestBT->getKind() == BuiltinType::Bool) + return RValue::get(ConvertScalarValueToBool(Val, ValTy)); + + // Handle pointer conversions next: pointers can only be converted to/from + // other pointers and integers. + if (isa<PointerType>(DstTy)) { + const llvm::Type *DestTy = ConvertType(DstTy); + + // The source value may be an integer, or a pointer. + assert(Val.isScalar() && "Can only convert from integer or pointer"); + if (isa<llvm::PointerType>(Val.getVal()->getType())) + return RValue::get(Builder.CreateBitCast(Val.getVal(), DestTy, "conv")); + assert(ValTy->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); + return RValue::get(Builder.CreatePtrToInt(Val.getVal(), DestTy, "conv")); + } + + if (isa<PointerType>(ValTy)) { + // Must be an ptr to int cast. + const llvm::Type *DestTy = ConvertType(DstTy); + assert(isa<llvm::IntegerType>(DestTy) && "not ptr->int?"); + return RValue::get(Builder.CreateIntToPtr(Val.getVal(), DestTy, "conv")); + } + + // Finally, we have the arithmetic types: real int/float and complex + // int/float. Handle real->real conversions first, they are the most + // common. + if (Val.isScalar() && DstTy->isRealType()) { + // We know that these are representable as scalars in LLVM, convert to LLVM + // types since they are easier to reason about. + llvm::Value *SrcVal = Val.getVal(); + const llvm::Type *DestTy = ConvertType(DstTy); + if (SrcVal->getType() == DestTy) return Val; + + llvm::Value *Result; + if (isa<llvm::IntegerType>(SrcVal->getType())) { + bool InputSigned = ValTy->isSignedIntegerType(); + if (isa<llvm::IntegerType>(DestTy)) + Result = Builder.CreateIntCast(SrcVal, DestTy, InputSigned, "conv"); + else if (InputSigned) + Result = Builder.CreateSIToFP(SrcVal, DestTy, "conv"); + else + Result = Builder.CreateUIToFP(SrcVal, DestTy, "conv"); + } else { + assert(SrcVal->getType()->isFloatingPoint() && "Unknown real conversion"); + if (isa<llvm::IntegerType>(DestTy)) { + if (DstTy->isSignedIntegerType()) + Result = Builder.CreateFPToSI(SrcVal, DestTy, "conv"); + else + Result = Builder.CreateFPToUI(SrcVal, DestTy, "conv"); + } else { + assert(DestTy->isFloatingPoint() && "Unknown real conversion"); + if (DestTy->getTypeID() < SrcVal->getType()->getTypeID()) + Result = Builder.CreateFPTrunc(SrcVal, DestTy, "conv"); + else + Result = Builder.CreateFPExt(SrcVal, DestTy, "conv"); + } + } + return RValue::get(Result); + } + + assert(0 && "FIXME: We don't support complex conversions yet!"); +} + + +/// ConvertScalarValueToBool - Convert the specified expression value to a +/// boolean (i1) truth value. This is equivalent to "Val == 0". +llvm::Value *CodeGenFunction::ConvertScalarValueToBool(RValue Val, QualType Ty){ + Ty = Ty.getCanonicalType(); + llvm::Value *Result; + if (const BuiltinType *BT = dyn_cast<BuiltinType>(Ty)) { + switch (BT->getKind()) { + default: assert(0 && "Unknown scalar value"); + case BuiltinType::Bool: + Result = Val.getVal(); + // Bool is already evaluated right. + assert(Result->getType() == llvm::Type::Int1Ty && + "Unexpected bool value type!"); + return Result; + 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: + // Code below handles simple integers. + break; + case BuiltinType::Float: + case BuiltinType::Double: + case BuiltinType::LongDouble: { + // Compare against 0.0 for fp scalars. + Result = Val.getVal(); + llvm::Value *Zero = llvm::Constant::getNullValue(Result->getType()); + // FIXME: llvm-gcc produces a une comparison: validate this is right. + Result = Builder.CreateFCmpUNE(Result, Zero, "tobool"); + return Result; + } + } + } else if (isa<PointerType>(Ty) || + cast<TagType>(Ty)->getDecl()->getKind() == Decl::Enum) { + // Code below handles this fine. + } else { + assert(isa<ComplexType>(Ty) && "Unknwon type!"); + assert(0 && "FIXME: comparisons against complex not implemented yet"); + } + + // Usual case for integers, pointers, and enums: compare against zero. + Result = Val.getVal(); + + // 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>(Result)) { + if (ZI->getOperand(0)->getType() == llvm::Type::Int1Ty) { + Result = ZI->getOperand(0); + ZI->eraseFromParent(); + return Result; + } + } + + llvm::Value *Zero = llvm::Constant::getNullValue(Result->getType()); + return Builder.CreateICmpNE(Result, Zero, "tobool"); +} + +//===----------------------------------------------------------------------===// +// 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: + fprintf(stderr, "Unimplemented lvalue expr!\n"); + E->dump(); + return LValue::MakeAddr(llvm::UndefValue::get( + llvm::PointerType::get(llvm::Type::Int32Ty))); + + case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E)); + case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); + case Expr::StringLiteralClass: + return EmitStringLiteralLValue(cast<StringLiteral>(E)); + + case Expr::UnaryOperatorClass: + return EmitUnaryOpLValue(cast<UnaryOperator>(E)); + case Expr::ArraySubscriptExprClass: + return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(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) { + ExprType = ExprType.getCanonicalType(); + + 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()) + return RValue::get(Builder.CreateLoad(Ptr, "tmp")); + + // Otherwise, we have an aggregate lvalue. + return RValue::getAggregate(Ptr); + } + + if (LV.isVectorElt()) { + llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), "tmp"); + return RValue::get(Builder.CreateExtractElement(Vec, LV.getVectorIdx(), + "vecext")); + } + + assert(0 && "Bitfield ref not impl!"); +} + +RValue CodeGenFunction::EmitLoadOfLValue(const Expr *E) { + return EmitLoadOfLValue(EmitLValue(E), E->getType()); +} + + +/// 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.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.getVal(), + Dst.getVectorIdx(), "vecins"); + Builder.CreateStore(Vec, Dst.getVectorAddr()); + return; + } + + assert(Dst.isSimple() && "FIXME: Don't support store to bitfield yet"); + + llvm::Value *DstAddr = Dst.getAddress(); + if (Src.isScalar()) { + // FIXME: Handle volatility etc. + const llvm::Type *SrcTy = Src.getVal()->getType(); + const llvm::Type *AddrTy = + cast<llvm::PointerType>(DstAddr->getType())->getElementType(); + + if (AddrTy != SrcTy) + DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy), + "storetmp"); + Builder.CreateStore(Src.getVal(), DstAddr); + return; + } + + // Don't use memcpy for complex numbers. + if (Ty->isComplexType()) { + llvm::Value *Real, *Imag; + EmitLoadOfComplex(Src, Real, Imag); + EmitStoreOfComplex(Real, Imag, Dst.getAddress()); + return; + } + + // Aggregate assignment turns into llvm.memcpy. + const llvm::Type *SBP = llvm::PointerType::get(llvm::Type::Int8Ty); + llvm::Value *SrcAddr = Src.getAggregateAddr(); + + if (DstAddr->getType() != SBP) + DstAddr = Builder.CreateBitCast(DstAddr, SBP, "tmp"); + if (SrcAddr->getType() != SBP) + SrcAddr = Builder.CreateBitCast(SrcAddr, SBP, "tmp"); + + unsigned Align = 1; // FIXME: Compute type alignments. + unsigned Size = 1234; // FIXME: Compute type sizes. + + // FIXME: Handle variable sized types. + const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); + llvm::Value *SizeVal = llvm::ConstantInt::get(IntPtr, Size); + + llvm::Value *MemCpyOps[4] = { + DstAddr, SrcAddr, SizeVal,llvm::ConstantInt::get(llvm::Type::Int32Ty, Align) + }; + + Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, 4); +} + + +LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { + const Decl *D = E->getDecl(); + if (isa<BlockVarDecl>(D) || isa<ParmVarDecl>(D)) { + llvm::Value *V = LocalDeclMap[D]; + assert(V && "BlockVarDecl not entered in LocalDeclMap?"); + return LValue::MakeAddr(V); + } else if (isa<FunctionDecl>(D) || isa<FileVarDecl>(D)) { + return LValue::MakeAddr(CGM.GetAddrOfGlobalDecl(D)); + } + assert(0 && "Unimp declref"); +} + +LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { + // __extension__ doesn't affect lvalue-ness. + if (E->getOpcode() == UnaryOperator::Extension) + return EmitLValue(E->getSubExpr()); + + assert(E->getOpcode() == UnaryOperator::Deref && + "'*' is the only unary operator that produces an lvalue"); + return LValue::MakeAddr(EmitExpr(E->getSubExpr()).getVal()); +} + +LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { + assert(!E->isWide() && "FIXME: Wide strings not supported yet!"); + const char *StrData = E->getStrData(); + unsigned Len = E->getByteLength(); + + // FIXME: Can cache/reuse these within the module. + llvm::Constant *C=llvm::ConstantArray::get(std::string(StrData, StrData+Len)); + + // Create a global variable for this. + C = new llvm::GlobalVariable(C->getType(), true, + llvm::GlobalValue::InternalLinkage, + C, ".str", CurFn->getParent()); + llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty); + llvm::Constant *Zeros[] = { Zero, Zero }; + C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2); + return LValue::MakeAddr(C); +} + +LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { + // The index must always be a pointer or integer, neither of which is an + // aggregate. Emit it. + QualType IdxTy; + llvm::Value *Idx = + EmitExprWithUsualUnaryConversions(E->getIdx(), IdxTy).getVal(); + + // If the base is a vector type, then we are forming a vector element lvalue + // with this subscript. + if (E->getBase()->getType()->isVectorType()) { + // Emit the vector as an lvalue to get its address. + LValue Base = EmitLValue(E->getBase()); + assert(Base.isSimple() && "Can only subscript lvalue vectors here!"); + // FIXME: This should properly sign/zero/extend or truncate Idx to i32. + return LValue::MakeVectorElt(Base.getAddress(), Idx); + } + + // At this point, the base must be a pointer or integer, neither of which are + // aggregates. Emit it. + QualType BaseTy; + llvm::Value *Base = + EmitExprWithUsualUnaryConversions(E->getBase(), BaseTy).getVal(); + + // Usually the base is the pointer type, but sometimes it is the index. + // Canonicalize to have the pointer as the base. + if (isa<llvm::PointerType>(Idx->getType())) { + std::swap(Base, Idx); + std::swap(BaseTy, IdxTy); + } + + // The pointer is now the base. Extend or truncate the index type to 32 or + // 64-bits. + 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")); +} + +//===--------------------------------------------------------------------===// +// Expression Emission +//===--------------------------------------------------------------------===// + +RValue CodeGenFunction::EmitExpr(const Expr *E) { + assert(E && "Null expression?"); + + switch (E->getStmtClass()) { + default: + fprintf(stderr, "Unimplemented expr!\n"); + E->dump(); + return RValue::get(llvm::UndefValue::get(llvm::Type::Int32Ty)); + + // l-values. + case Expr::DeclRefExprClass: + // DeclRef's of EnumConstantDecl's are simple rvalues. + if (const EnumConstantDecl *EC = + dyn_cast<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) + return RValue::get(llvm::ConstantInt::get(EC->getInitVal())); + return EmitLoadOfLValue(E); + case Expr::ArraySubscriptExprClass: + return EmitArraySubscriptExprRV(cast<ArraySubscriptExpr>(E)); + case Expr::StringLiteralClass: + return RValue::get(EmitLValue(E).getAddress()); + + // Leaf expressions. + case Expr::IntegerLiteralClass: + return EmitIntegerLiteral(cast<IntegerLiteral>(E)); + case Expr::FloatingLiteralClass: + return EmitFloatingLiteral(cast<FloatingLiteral>(E)); + + // Operators. + case Expr::ParenExprClass: + return EmitExpr(cast<ParenExpr>(E)->getSubExpr()); + case Expr::UnaryOperatorClass: + return EmitUnaryOperator(cast<UnaryOperator>(E)); + case Expr::CastExprClass: + return EmitCastExpr(cast<CastExpr>(E)); + case Expr::CallExprClass: + return EmitCallExpr(cast<CallExpr>(E)); + case Expr::BinaryOperatorClass: + return EmitBinaryOperator(cast<BinaryOperator>(E)); + } + +} + +RValue CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) { + return RValue::get(llvm::ConstantInt::get(E->getValue())); +} +RValue CodeGenFunction::EmitFloatingLiteral(const FloatingLiteral *E) { + return RValue::get(llvm::ConstantFP::get(ConvertType(E->getType()), + E->getValue())); +} + + +RValue CodeGenFunction::EmitArraySubscriptExprRV(const 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. + QualType BaseTy, IdxTy; + llvm::Value *Base = + EmitExprWithUsualUnaryConversions(E->getBase(), BaseTy).getVal(); + llvm::Value *Idx = + EmitExprWithUsualUnaryConversions(E->getIdx(), IdxTy).getVal(); + + // FIXME: Convert Idx to i32 type. + + return RValue::get(Builder.CreateExtractElement(Base, Idx, "vecext")); +} + + +RValue CodeGenFunction::EmitCastExpr(const CastExpr *E) { + QualType SrcTy; + RValue Src = EmitExprWithUsualUnaryConversions(E->getSubExpr(), SrcTy); + + // If the destination is void, just evaluate the source. + if (E->getType()->isVoidType()) + return RValue::getAggregate(0); + + return EmitConversion(Src, SrcTy, E->getType()); +} + +RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { + QualType CalleeTy; + llvm::Value *Callee = + EmitExprWithUsualUnaryConversions(E->getCallee(), CalleeTy).getVal(); + + // The callee type will always be a pointer to function type, get the function + // type. + CalleeTy = cast<PointerType>(CalleeTy.getCanonicalType())->getPointeeType(); + + // Get information about the argument types. + FunctionTypeProto::arg_type_iterator ArgTyIt = 0, ArgTyEnd = 0; + + // Calling unprototyped functions provides no argument info. + if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(CalleeTy)) { + ArgTyIt = FTP->arg_type_begin(); + ArgTyEnd = FTP->arg_type_end(); + } + + llvm::SmallVector<llvm::Value*, 16> Args; + + // FIXME: Handle struct return. + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { + QualType ArgTy; + RValue ArgVal = EmitExprWithUsualUnaryConversions(E->getArg(i), ArgTy); + + // If this argument has prototype information, convert it. + if (ArgTyIt != ArgTyEnd) { + ArgVal = EmitConversion(ArgVal, ArgTy, *ArgTyIt++); + } else { + // Otherwise, if passing through "..." or to a function with no prototype, + // perform the "default argument promotions" (C99 6.5.2.2p6), which + // includes the usual unary conversions, but also promotes float to + // double. + if (const BuiltinType *BT = + dyn_cast<BuiltinType>(ArgTy.getCanonicalType())) { + if (BT->getKind() == BuiltinType::Float) + ArgVal = RValue::get(Builder.CreateFPExt(ArgVal.getVal(), + llvm::Type::DoubleTy,"tmp")); + } + } + + + if (ArgVal.isScalar()) + Args.push_back(ArgVal.getVal()); + else // Pass by-address. FIXME: Set attribute bit on call. + Args.push_back(ArgVal.getAggregateAddr()); + } + + llvm::Value *V = Builder.CreateCall(Callee, &Args[0], Args.size()); + if (V->getType() != llvm::Type::VoidTy) + V->setName("call"); + + // FIXME: Struct return; + return RValue::get(V); +} + + +//===----------------------------------------------------------------------===// +// Unary Operator Emission +//===----------------------------------------------------------------------===// + +RValue CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E, + QualType &ResTy) { + ResTy = E->getType().getCanonicalType(); + + if (isa<FunctionType>(ResTy)) { // C99 6.3.2.1p4 + // Functions are promoted to their address. + ResTy = getContext().getPointerType(ResTy); + return RValue::get(EmitLValue(E).getAddress()); + } else if (const ArrayType *ary = dyn_cast<ArrayType>(ResTy)) { + // C99 6.3.2.1p3 + ResTy = getContext().getPointerType(ary->getElementType()); + + // FIXME: For now we assume that all source arrays map to LLVM arrays. This + // will not true when we add support for VLAs. + llvm::Value *V = EmitLValue(E).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); + return RValue::get(Builder.CreateGEP(V, Idx0, Idx0, "arraydecay")); + } else if (ResTy->isPromotableIntegerType()) { // C99 6.3.1.1p2 + // FIXME: this probably isn't right, pending clarification from Steve. + llvm::Value *Val = EmitExpr(E).getVal(); + + // If the input is a signed integer, sign extend to the destination. + if (ResTy->isSignedIntegerType()) { + Val = Builder.CreateSExt(Val, LLVMIntTy, "promote"); + } else { + // This handles unsigned types, including bool. + Val = Builder.CreateZExt(Val, LLVMIntTy, "promote"); + } + ResTy = getContext().IntTy; + + return RValue::get(Val); + } + + // Otherwise, this is a float, double, int, struct, etc. + return EmitExpr(E); +} + + +RValue CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) { + switch (E->getOpcode()) { + default: + printf("Unimplemented unary expr!\n"); + E->dump(); + return RValue::get(llvm::UndefValue::get(llvm::Type::Int32Ty)); + // FIXME: pre/post inc/dec + case UnaryOperator::AddrOf: return EmitUnaryAddrOf(E); + case UnaryOperator::Deref : return EmitLoadOfLValue(E); + case UnaryOperator::Plus : return EmitUnaryPlus(E); + case UnaryOperator::Minus : return EmitUnaryMinus(E); + case UnaryOperator::Not : return EmitUnaryNot(E); + case UnaryOperator::LNot : return EmitUnaryLNot(E); + // FIXME: SIZEOF/ALIGNOF(expr). + // FIXME: real/imag + case UnaryOperator::Extension: return EmitExpr(E->getSubExpr()); + } +} + +/// C99 6.5.3.2 +RValue CodeGenFunction::EmitUnaryAddrOf(const UnaryOperator *E) { + // The address of the operand is just its lvalue. It cannot be a bitfield. + return RValue::get(EmitLValue(E->getSubExpr()).getAddress()); +} + +RValue CodeGenFunction::EmitUnaryPlus(const UnaryOperator *E) { + // Unary plus just performs promotions on its arithmetic operand. + QualType Ty; + return EmitExprWithUsualUnaryConversions(E->getSubExpr(), Ty); +} + +RValue CodeGenFunction::EmitUnaryMinus(const UnaryOperator *E) { + // Unary minus performs promotions, then negates its arithmetic operand. + QualType Ty; + RValue V = EmitExprWithUsualUnaryConversions(E->getSubExpr(), Ty); + + if (V.isScalar()) + return RValue::get(Builder.CreateNeg(V.getVal(), "neg")); + + assert(0 && "FIXME: This doesn't handle complex operands yet"); +} + +RValue CodeGenFunction::EmitUnaryNot(const UnaryOperator *E) { + // Unary not performs promotions, then complements its integer operand. + QualType Ty; + RValue V = EmitExprWithUsualUnaryConversions(E->getSubExpr(), Ty); + + if (V.isScalar()) + return RValue::get(Builder.CreateNot(V.getVal(), "neg")); + + assert(0 && "FIXME: This doesn't handle integer complex operands yet (GNU)"); +} + + +/// C99 6.5.3.3 +RValue CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) { + // Compare operand to zero. + llvm::Value *BoolVal = 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 RValue::get(Builder.CreateZExt(BoolVal, LLVMIntTy, "lnot.ext")); +} + + +//===--------------------------------------------------------------------===// +// Binary Operator Emission +//===--------------------------------------------------------------------===// + +// FIXME describe. +QualType CodeGenFunction:: +EmitUsualArithmeticConversions(const BinaryOperator *E, RValue &LHS, + RValue &RHS) { + QualType LHSType, RHSType; + LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), LHSType); + RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSType); + + // If both operands have the same source type, we're done already. + if (LHSType == RHSType) return LHSType; + + // If either side is a non-arithmetic type (e.g. a pointer), we are done. + // The caller can deal with this (e.g. pointer + int). + if (!LHSType->isArithmeticType() || !RHSType->isArithmeticType()) + return LHSType; + + // At this point, we have two different arithmetic types. + + // Handle complex types first (C99 6.3.1.8p1). + if (LHSType->isComplexType() || RHSType->isComplexType()) { + assert(0 && "FIXME: complex types unimp"); +#if 0 + // if we have an integer operand, the result is the complex type. + if (rhs->isIntegerType()) + return lhs; + if (lhs->isIntegerType()) + return rhs; + return Context.maxComplexType(lhs, rhs); +#endif + } + + // If neither operand is complex, they must be scalars. + llvm::Value *LHSV = LHS.getVal(); + llvm::Value *RHSV = RHS.getVal(); + + // If the LLVM types are already equal, then they only differed in sign, or it + // was something like char/signed char or double/long double. + if (LHSV->getType() == RHSV->getType()) + return LHSType; + + // Now handle "real" floating types (i.e. float, double, long double). + if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType()) { + // if we have an integer operand, the result is the real floating type, and + // the integer converts to FP. + if (RHSType->isIntegerType()) { + // Promote the RHS to an FP type of the LHS, with the sign following the + // RHS. + if (RHSType->isSignedIntegerType()) + RHS = RValue::get(Builder.CreateSIToFP(RHSV,LHSV->getType(),"promote")); + else + RHS = RValue::get(Builder.CreateUIToFP(RHSV,LHSV->getType(),"promote")); + return LHSType; + } + + if (LHSType->isIntegerType()) { + // Promote the LHS to an FP type of the RHS, with the sign following the + // LHS. + if (LHSType->isSignedIntegerType()) + LHS = RValue::get(Builder.CreateSIToFP(LHSV,RHSV->getType(),"promote")); + else + LHS = RValue::get(Builder.CreateUIToFP(LHSV,RHSV->getType(),"promote")); + return RHSType; + } + + // Otherwise, they are two FP types. Promote the smaller operand to the + // bigger result. + QualType BiggerType = ASTContext::maxFloatingType(LHSType, RHSType); + + if (BiggerType == LHSType) + RHS = RValue::get(Builder.CreateFPExt(RHSV, LHSV->getType(), "promote")); + else + LHS = RValue::get(Builder.CreateFPExt(LHSV, RHSV->getType(), "promote")); + return BiggerType; + } + + // Finally, we have two integer types that are different according to C. Do + // a sign or zero extension if needed. + + // Otherwise, one type is smaller than the other. + QualType ResTy = ASTContext::maxIntegerType(LHSType, RHSType); + + if (LHSType == ResTy) { + if (RHSType->isSignedIntegerType()) + RHS = RValue::get(Builder.CreateSExt(RHSV, LHSV->getType(), "promote")); + else + RHS = RValue::get(Builder.CreateZExt(RHSV, LHSV->getType(), "promote")); + } else { + assert(RHSType == ResTy && "Unknown conversion"); + if (LHSType->isSignedIntegerType()) + LHS = RValue::get(Builder.CreateSExt(LHSV, RHSV->getType(), "promote")); + else + LHS = RValue::get(Builder.CreateZExt(LHSV, RHSV->getType(), "promote")); + } + return ResTy; +} + +/// EmitCompoundAssignmentOperands - Compound assignment operations (like +=) +/// are strange in that the result of the operation is not the same type as the +/// intermediate computation. This function emits the LHS and RHS operands of +/// the compound assignment, promoting them to their common computation type. +/// +/// Since the LHS is an lvalue, and the result is stored back through it, we +/// return the lvalue as well as the LHS/RHS rvalues. On return, the LHS and +/// RHS values are both in the computation type for the operator. +void CodeGenFunction:: +EmitCompoundAssignmentOperands(const CompoundAssignOperator *E, + LValue &LHSLV, RValue &LHS, RValue &RHS) { + LHSLV = EmitLValue(E->getLHS()); + + // Load the LHS and RHS operands. + QualType LHSTy = E->getLHS()->getType(); + LHS = EmitLoadOfLValue(LHSLV, LHSTy); + QualType RHSTy; + RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSTy); + + // Shift operands do the usual unary conversions, but do not do the binary + // conversions. + if (E->isShiftAssignOp()) { + // FIXME: This is broken. Implicit conversions should be made explicit, + // so that this goes away. This causes us to reload the LHS. + LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), LHSTy); + } + + // Convert the LHS and RHS to the common evaluation type. + LHS = EmitConversion(LHS, LHSTy, E->getComputationType()); + RHS = EmitConversion(RHS, RHSTy, E->getComputationType()); +} + +/// EmitCompoundAssignmentResult - Given a result value in the computation type, +/// truncate it down to the actual result type, store it through the LHS lvalue, +/// and return it. +RValue CodeGenFunction:: +EmitCompoundAssignmentResult(const CompoundAssignOperator *E, + LValue LHSLV, RValue ResV) { + + // Truncate back to the destination type. + if (E->getComputationType() != E->getType()) + ResV = EmitConversion(ResV, E->getComputationType(), E->getType()); + + // Store the result value into the LHS. + EmitStoreThroughLValue(ResV, LHSLV, E->getType()); + + // Return the result. + return ResV; +} + + +RValue CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) { + RValue LHS, RHS; + switch (E->getOpcode()) { + default: + fprintf(stderr, "Unimplemented binary expr!\n"); + E->dump(); + return RValue::get(llvm::UndefValue::get(llvm::Type::Int32Ty)); + case BinaryOperator::Mul: + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitMul(LHS, RHS, E->getType()); + case BinaryOperator::Div: + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitDiv(LHS, RHS, E->getType()); + case BinaryOperator::Rem: + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitRem(LHS, RHS, E->getType()); + case BinaryOperator::Add: + // FIXME: This doesn't handle ptr+int etc yet. + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitAdd(LHS, RHS, E->getType()); + case BinaryOperator::Sub: + // FIXME: This doesn't handle ptr-int etc yet. + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitSub(LHS, RHS, E->getType()); + case BinaryOperator::Shl: + EmitShiftOperands(E, LHS, RHS); + return EmitShl(LHS, RHS, E->getType()); + case BinaryOperator::Shr: + EmitShiftOperands(E, LHS, RHS); + return EmitShr(LHS, RHS, E->getType()); + case BinaryOperator::And: + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitAnd(LHS, RHS, E->getType()); + case BinaryOperator::Xor: + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitXor(LHS, RHS, E->getType()); + case BinaryOperator::Or : + EmitUsualArithmeticConversions(E, LHS, RHS); + return EmitOr(LHS, RHS, E->getType()); + case BinaryOperator::LAnd: return EmitBinaryLAnd(E); + case BinaryOperator::LOr: return EmitBinaryLOr(E); + case BinaryOperator::LT: + return EmitBinaryCompare(E, llvm::ICmpInst::ICMP_ULT, + llvm::ICmpInst::ICMP_SLT, + llvm::FCmpInst::FCMP_OLT); + case BinaryOperator::GT: + return EmitBinaryCompare(E, llvm::ICmpInst::ICMP_UGT, + llvm::ICmpInst::ICMP_SGT, + llvm::FCmpInst::FCMP_OGT); + case BinaryOperator::LE: + return EmitBinaryCompare(E, llvm::ICmpInst::ICMP_ULE, + llvm::ICmpInst::ICMP_SLE, + llvm::FCmpInst::FCMP_OLE); + case BinaryOperator::GE: + return EmitBinaryCompare(E, llvm::ICmpInst::ICMP_UGE, + llvm::ICmpInst::ICMP_SGE, + llvm::FCmpInst::FCMP_OGE); + case BinaryOperator::EQ: + return EmitBinaryCompare(E, llvm::ICmpInst::ICMP_EQ, + llvm::ICmpInst::ICMP_EQ, + llvm::FCmpInst::FCMP_OEQ); + case BinaryOperator::NE: + return EmitBinaryCompare(E, llvm::ICmpInst::ICMP_NE, + llvm::ICmpInst::ICMP_NE, + llvm::FCmpInst::FCMP_UNE); + case BinaryOperator::Assign: + return EmitBinaryAssign(E); + + case BinaryOperator::MulAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitMul(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::DivAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitDiv(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::RemAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitRem(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::AddAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitAdd(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::SubAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitSub(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::ShlAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitShl(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::ShrAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitShr(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::AndAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitAnd(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::OrAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitOr(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::XorAssign: { + const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E); + LValue LHSLV; + EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS); + LHS = EmitXor(LHS, RHS, CAO->getComputationType()); + return EmitCompoundAssignmentResult(CAO, LHSLV, LHS); + } + case BinaryOperator::Comma: return EmitBinaryComma(E); + } +} + +RValue CodeGenFunction::EmitMul(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) + return RValue::get(Builder.CreateMul(LHS.getVal(), RHS.getVal(), "mul")); + + assert(0 && "FIXME: This doesn't handle complex operands yet"); +} + +RValue CodeGenFunction::EmitDiv(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) { + llvm::Value *RV; + if (LHS.getVal()->getType()->isFloatingPoint()) + RV = Builder.CreateFDiv(LHS.getVal(), RHS.getVal(), "div"); + else if (ResTy->isUnsignedIntegerType()) + RV = Builder.CreateUDiv(LHS.getVal(), RHS.getVal(), "div"); + else + RV = Builder.CreateSDiv(LHS.getVal(), RHS.getVal(), "div"); + return RValue::get(RV); + } + assert(0 && "FIXME: This doesn't handle complex operands yet"); +} + +RValue CodeGenFunction::EmitRem(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) { + llvm::Value *RV; + // Rem in C can't be a floating point type: C99 6.5.5p2. + if (ResTy->isUnsignedIntegerType()) + RV = Builder.CreateURem(LHS.getVal(), RHS.getVal(), "rem"); + else + RV = Builder.CreateSRem(LHS.getVal(), RHS.getVal(), "rem"); + return RValue::get(RV); + } + + assert(0 && "FIXME: This doesn't handle complex operands yet"); +} + +RValue CodeGenFunction::EmitAdd(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) + return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add")); + + // Otherwise, this must be a complex number. + llvm::Value *LHSR, *LHSI, *RHSR, *RHSI; + + EmitLoadOfComplex(LHS, LHSR, LHSI); + EmitLoadOfComplex(RHS, RHSR, RHSI); + + llvm::Value *ResR = Builder.CreateAdd(LHSR, RHSR, "add.r"); + llvm::Value *ResI = Builder.CreateAdd(LHSI, RHSI, "add.i"); + + llvm::Value *Res = CreateTempAlloca(ConvertType(ResTy)); + EmitStoreOfComplex(ResR, ResI, Res); + return RValue::getAggregate(Res); +} + +RValue CodeGenFunction::EmitSub(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) + return RValue::get(Builder.CreateSub(LHS.getVal(), RHS.getVal(), "sub")); + + assert(0 && "FIXME: This doesn't handle complex operands yet"); +} + +void CodeGenFunction::EmitShiftOperands(const BinaryOperator *E, + RValue &LHS, RValue &RHS) { + // For shifts, integer promotions are performed, but the usual arithmetic + // conversions are not. The LHS and RHS need not have the same type. + QualType ResTy; + LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), ResTy); + RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), ResTy); +} + + +RValue CodeGenFunction::EmitShl(RValue LHSV, RValue RHSV, QualType ResTy) { + llvm::Value *LHS = LHSV.getVal(), *RHS = RHSV.getVal(); + + // 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 = Builder.CreateIntCast(RHS, LHS->getType(), false, "sh_prom"); + + return RValue::get(Builder.CreateShl(LHS, RHS, "shl")); +} + +RValue CodeGenFunction::EmitShr(RValue LHSV, RValue RHSV, QualType ResTy) { + llvm::Value *LHS = LHSV.getVal(), *RHS = RHSV.getVal(); + + // 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 = Builder.CreateIntCast(RHS, LHS->getType(), false, "sh_prom"); + + if (ResTy->isUnsignedIntegerType()) + return RValue::get(Builder.CreateLShr(LHS, RHS, "shr")); + else + return RValue::get(Builder.CreateAShr(LHS, RHS, "shr")); +} + +RValue CodeGenFunction::EmitBinaryCompare(const BinaryOperator *E, + unsigned UICmpOpc, unsigned SICmpOpc, + unsigned FCmpOpc) { + RValue LHS, RHS; + EmitUsualArithmeticConversions(E, LHS, RHS); + + llvm::Value *Result; + if (LHS.isScalar()) { + if (LHS.getVal()->getType()->isFloatingPoint()) { + Result = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc, + LHS.getVal(), RHS.getVal(), "cmp"); + } else if (E->getLHS()->getType()->isUnsignedIntegerType()) { + // FIXME: This check isn't right for "unsigned short < int" where ushort + // promotes to int and does a signed compare. + Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc, + LHS.getVal(), RHS.getVal(), "cmp"); + } else { + // Signed integers and pointers. + Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)SICmpOpc, + LHS.getVal(), RHS.getVal(), "cmp"); + } + } else { + // Struct/union/complex + assert(0 && "Aggregate comparisons not implemented yet!"); + } + + // ZExt result to int. + return RValue::get(Builder.CreateZExt(Result, LLVMIntTy, "cmp.ext")); +} + +RValue CodeGenFunction::EmitAnd(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) + return RValue::get(Builder.CreateAnd(LHS.getVal(), RHS.getVal(), "and")); + + assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)"); +} + +RValue CodeGenFunction::EmitXor(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) + return RValue::get(Builder.CreateXor(LHS.getVal(), RHS.getVal(), "xor")); + + assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)"); +} + +RValue CodeGenFunction::EmitOr(RValue LHS, RValue RHS, QualType ResTy) { + if (LHS.isScalar()) + return RValue::get(Builder.CreateOr(LHS.getVal(), RHS.getVal(), "or")); + + assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)"); +} + +RValue CodeGenFunction::EmitBinaryLAnd(const BinaryOperator *E) { + llvm::Value *LHSCond = 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); + + EmitBlock(RHSBlock); + llvm::Value *RHSCond = EvaluateExprAsBool(E->getRHS()); + + // Reaquire the RHS block, as there may be subblocks inserted. + RHSBlock = Builder.GetInsertBlock(); + 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 RValue::get(Builder.CreateZExt(PN, LLVMIntTy, "land.ext")); +} + +RValue CodeGenFunction::EmitBinaryLOr(const BinaryOperator *E) { + llvm::Value *LHSCond = 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); + + EmitBlock(RHSBlock); + llvm::Value *RHSCond = EvaluateExprAsBool(E->getRHS()); + + // Reaquire the RHS block, as there may be subblocks inserted. + RHSBlock = Builder.GetInsertBlock(); + 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 RValue::get(Builder.CreateZExt(PN, LLVMIntTy, "lor.ext")); +} + +RValue CodeGenFunction::EmitBinaryAssign(const BinaryOperator *E) { + LValue LHS = EmitLValue(E->getLHS()); + + QualType RHSTy; + RValue RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSTy); + + // Convert the RHS to the type of the LHS. + RHS = EmitConversion(RHS, RHSTy, E->getType()); + + // Store the value into the LHS. + EmitStoreThroughLValue(RHS, LHS, E->getType()); + + // Return the converted RHS. + return RHS; +} + + +RValue CodeGenFunction::EmitBinaryComma(const BinaryOperator *E) { + EmitExpr(E->getLHS()); + return EmitExpr(E->getRHS()); +} diff --git a/CodeGen/CGStmt.cpp b/CodeGen/CGStmt.cpp new file mode 100644 index 0000000000..fb2f7841f2 --- /dev/null +++ b/CodeGen/CGStmt.cpp @@ -0,0 +1,284 @@ +//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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 "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.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 and ignore the + // result. + if (const Expr *E = dyn_cast<Expr>(S)) { + EmitExpr(E); + } else { + printf("Unimplemented stmt!\n"); + S->dump(); + } + 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; + } +} + +void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) { + // FIXME: handle vla's etc. + + for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end(); + I != E; ++I) + EmitStmt(*I); +} + +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()); + Builder.CreateBr(ContBlock); + + // Emit the 'else' code if present. + if (const Stmt *Else = S.getElse()) { + EmitBlock(ElseBlock); + EmitStmt(Else); + Builder.CreateBr(ContBlock); + } + + // Emit the continuation block for code after the if. + EmitBlock(ContBlock); +} + +void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { + // FIXME: Handle continue/break. + + // 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()); + + // TODO: while(1) is common, avoid extra exit blocks, etc. Be sure + // to correctly handle break/continue though. + + // 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. + Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); + + // Emit the loop body. + EmitBlock(LoopBody); + EmitStmt(S.getBody()); + + // Cycle to the condition. + Builder.CreateBr(LoopHeader); + + // Emit the exit block. + EmitBlock(ExitBlock); +} + +void CodeGenFunction::EmitDoStmt(const DoStmt &S) { + // FIXME: Handle continue/break. + // TODO: "do {} while (0)" is common in macros, avoid extra blocks. Be sure + // to correctly handle break/continue though. + + // 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); + + // Emit the body of the loop into the block. + EmitStmt(S.getBody()); + + // 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()); + + // As long as the condition is true, iterate the loop. + Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo); + + // Emit the exit block. + EmitBlock(AfterDo); +} + +void CodeGenFunction::EmitForStmt(const ForStmt &S) { + // FIXME: Handle continue/break. + // FIXME: What do we do if the increment (f.e.) contains a stmt expression, + // which contains a continue/break? + + // 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 = 0; + 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"); + AfterFor = new llvm::BasicBlock("afterfor"); + 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 condition is true, execute the body of the for stmt. + EmitStmt(S.getBody()); + + // If there is an increment, emit it next. + if (S.getInc()) + EmitExpr(S.getInc()); + + // Finally, branch back up to the condition for the next iteration. + Builder.CreateBr(CondBlock); + + // Emit the fall-through block if there is any. + if (AfterFor) + EmitBlock(AfterFor); + else + EmitBlock(new llvm::BasicBlock()); +} + +/// 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) { + RValue RetVal; + + // Emit the result value, even if unused, to evalute the side effects. + const Expr *RV = S.getRetValue(); + if (RV) + RetVal = EmitExpr(RV); + + QualType FnRetTy = CurFuncDecl->getType().getCanonicalType(); + FnRetTy = cast<FunctionType>(FnRetTy)->getResultType(); + + if (FnRetTy->isVoidType()) { + // If the function returns void, emit ret void, and ignore the retval. + Builder.CreateRetVoid(); + } else if (RV == 0) { + // "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 { + // Do implicit conversions to the returned type. + RetVal = EmitConversion(RetVal, RV->getType(), FnRetTy); + + if (RetVal.isScalar()) { + Builder.CreateRet(RetVal.getVal()); + } else { + llvm::Value *SRetPtr = CurFn->arg_begin(); + EmitStoreThroughLValue(RetVal, LValue::MakeAddr(SRetPtr), FnRetTy); + } + } + + // 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 Decl *Decl = S.getDecl(); Decl; Decl = Decl->getNextDeclarator()) + EmitDecl(*Decl); +}
\ No newline at end of file diff --git a/CodeGen/CodeGenFunction.cpp b/CodeGen/CodeGenFunction.cpp new file mode 100644 index 0000000000..662c3b513c --- /dev/null +++ b/CodeGen/CodeGenFunction.cpp @@ -0,0 +1,98 @@ +//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Analysis/Verifier.h" +using namespace clang; +using namespace CodeGen; + +CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) + : CGM(cgm), Target(CGM.getContext().Target) {} + +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()); +} + + +const llvm::Type *CodeGenFunction::ConvertType(QualType T) { + return CGM.getTypes().ConvertType(T); +} + +bool CodeGenFunction::hasAggregateLLVMType(QualType T) { + return !T->isRealType() && !T->isPointerType() && !T->isVoidType() && + !T->isVectorType(); +} + + +void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { + LLVMIntTy = ConvertType(getContext().IntTy); + LLVMPointerWidth = Target.getPointerWidth(SourceLocation()); + + CurFn = cast<llvm::Function>(CGM.GetAddrOfGlobalDecl(FD)); + CurFuncDecl = FD; + + // TODO: Set up linkage and many other things. + assert(CurFn->isDeclaration() && "Function already has body?"); + + llvm::BasicBlock *EntryBB = new llvm::BasicBlock("entry", CurFn); + + Builder.SetInsertPoint(EntryBB); + + // Create a marker to make it easy to insert allocas into the entryblock + // later. + llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty); + AllocaInsertPt = Builder.CreateBitCast(Undef,llvm::Type::Int32Ty, "allocapt"); + + // 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. + // 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())); + + // Verify that the function is well formed. + assert(!verifyFunction(*CurFn)); +} + diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h new file mode 100644 index 0000000000..acefedf3cc --- /dev/null +++ b/CodeGen/CodeGenFunction.h @@ -0,0 +1,354 @@ +//===--- CodeGenFunction.h - Per-Function state for LLVM CodeGen ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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 CODEGEN_CODEGENFUNCTION_H +#define CODEGEN_CODEGENFUNCTION_H + +#include "llvm/ADT/DenseMap.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 Expr; + class DeclRefExpr; + class StringLiteral; + class IntegerLiteral; + class FloatingLiteral; + class CastExpr; + class CallExpr; + class UnaryOperator; + class BinaryOperator; + class CompoundAssignOperator; + class ArraySubscriptExpr; + + class BlockVarDecl; + class EnumConstantDecl; + class ParmVarDecl; +namespace CodeGen { + class CodeGenModule; + + +/// RValue - This trivial value class is used to represent the result of an +/// expression that is evaluated. It can be one of two things: either a simple +/// LLVM SSA value, or the address of an aggregate value in memory. These two +/// possibilities are discriminated by isAggregate/isScalar. +class RValue { + llvm::Value *V; + // TODO: Encode this into the low bit of pointer for more efficient + // return-by-value. + bool IsAggregate; + + // FIXME: Aggregate rvalues need to retain information about whether they are + // volatile or not. +public: + + bool isAggregate() const { return IsAggregate; } + bool isScalar() const { return !IsAggregate; } + + /// getVal() - Return the Value* of this scalar value. + llvm::Value *getVal() const { + assert(!isAggregate() && "Not a scalar!"); + return V; + } + + /// getAggregateAddr() - Return the Value* of the address of the aggregate. + llvm::Value *getAggregateAddr() const { + assert(isAggregate() && "Not an aggregate!"); + return V; + } + + static RValue get(llvm::Value *V) { + RValue ER; + ER.V = V; + ER.IsAggregate = false; + return ER; + } + static RValue getAggregate(llvm::Value *V) { + RValue ER; + ER.V = V; + ER.IsAggregate = true; + 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*. + } LVType; + + llvm::Value *V; + + union { + llvm::Value *VectorIdx; + }; +public: + bool isSimple() const { return LVType == Simple; } + bool isVectorElt() const { return LVType == VectorElt; } + bool isBitfield() const { return LVType == BitField; } + + // 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; } + + 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; + } + +}; + +/// CodeGenFunction - This class organizes the per-function state that is used +/// while generating LLVM code. +class CodeGenFunction { + CodeGenModule &CGM; // Per-module state. + TargetInfo &Target; + llvm::LLVMBuilder 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; + unsigned LLVMPointerWidth; + + /// 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; +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); + + //===--------------------------------------------------------------------===// + // 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); + + + /// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to + /// load the real and imaginary pieces, returning them as Real/Imag. + void EmitLoadOfComplex(RValue V, llvm::Value *&Real, llvm::Value *&Imag); + + /// EmitStoreOfComplex - Store the specified real/imag parts into the + /// specified value pointer. + void EmitStoreOfComplex(llvm::Value *Real, llvm::Value *Imag, + llvm::Value *ResPtr); + + //===--------------------------------------------------------------------===// + // Conversions + //===--------------------------------------------------------------------===// + + /// EmitConversion - Convert the value specied by Val, whose type is ValTy, to + /// the type specified by DstTy, following the rules of C99 6.3. + RValue EmitConversion(RValue Val, QualType ValTy, QualType DstTy); + + /// ConvertScalarValueToBool - Convert the specified expression value to a + /// boolean (i1) truth value. This is equivalent to "Val == 0". + llvm::Value *ConvertScalarValueToBool(RValue Val, QualType Ty); + + //===--------------------------------------------------------------------===// + // Declaration Emission + //===--------------------------------------------------------------------===// + + void EmitDecl(const Decl &D); + void EmitEnumConstantDecl(const EnumConstantDecl &D); + void EmitBlockVarDecl(const BlockVarDecl &D); + void EmitLocalBlockVarDecl(const BlockVarDecl &D); + void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg); + + //===--------------------------------------------------------------------===// + // Statement Emission + //===--------------------------------------------------------------------===// + + void EmitStmt(const Stmt *S); + void EmitCompoundStmt(const CompoundStmt &S); + 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); + + //===--------------------------------------------------------------------===// + // 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(const Expr *E); + RValue EmitLoadOfLValue(LValue V, QualType LVType); + + /// 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); + + LValue EmitDeclRefLValue(const DeclRefExpr *E); + LValue EmitStringLiteralLValue(const StringLiteral *E); + LValue EmitUnaryOpLValue(const UnaryOperator *E); + LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E); + + //===--------------------------------------------------------------------===// + // Expression Emission + //===--------------------------------------------------------------------===// + + RValue EmitExprWithUsualUnaryConversions(const Expr *E, QualType &ResTy); + QualType EmitUsualArithmeticConversions(const BinaryOperator *E, + RValue &LHS, RValue &RHS); + void EmitShiftOperands(const BinaryOperator *E, RValue &LHS, RValue &RHS); + + void EmitCompoundAssignmentOperands(const CompoundAssignOperator *CAO, + LValue &LHSLV, RValue &LHS, RValue &RHS); + RValue EmitCompoundAssignmentResult(const CompoundAssignOperator *E, + LValue LHSLV, RValue ResV); + + + RValue EmitExpr(const Expr *E); + RValue EmitIntegerLiteral(const IntegerLiteral *E); + RValue EmitFloatingLiteral(const FloatingLiteral *E); + + RValue EmitCastExpr(const CastExpr *E); + RValue EmitCallExpr(const CallExpr *E); + RValue EmitArraySubscriptExprRV(const ArraySubscriptExpr *E); + + // Unary Operators. + RValue EmitUnaryOperator(const UnaryOperator *E); + // FIXME: pre/post inc/dec + RValue EmitUnaryAddrOf (const UnaryOperator *E); + RValue EmitUnaryPlus (const UnaryOperator *E); + RValue EmitUnaryMinus (const UnaryOperator *E); + RValue EmitUnaryNot (const UnaryOperator *E); + RValue EmitUnaryLNot (const UnaryOperator *E); + // FIXME: SIZEOF/ALIGNOF(expr). + // FIXME: real/imag + + // Binary Operators. + RValue EmitBinaryOperator(const BinaryOperator *E); + RValue EmitBinaryMul(const BinaryOperator *E); + RValue EmitBinaryDiv(const BinaryOperator *E); + RValue EmitBinaryRem(const BinaryOperator *E); + RValue EmitMul(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitDiv(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitRem(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitAdd(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitSub(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitShl(RValue LHS, RValue RHS, QualType ResTy); + RValue EmitShr(RValue LHS, RValue RHS, QualType ResTy); + RValue EmitBinaryCompare(const BinaryOperator *E, unsigned UICmpOpc, + unsigned SICmpOpc, unsigned FCmpOpc); + RValue EmitAnd(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitOr (RValue LHS, RValue RHS, QualType EltTy); + RValue EmitXor(RValue LHS, RValue RHS, QualType EltTy); + RValue EmitBinaryLAnd(const BinaryOperator *E); + RValue EmitBinaryLOr(const BinaryOperator *E); + + RValue EmitBinaryAssign(const BinaryOperator *E); + RValue EmitBinaryComma(const BinaryOperator *E); +}; +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/CodeGen/CodeGenModule.cpp b/CodeGen/CodeGenModule.cpp new file mode 100644 index 0000000000..cdc3e63026 --- /dev/null +++ b/CodeGen/CodeGenModule.cpp @@ -0,0 +1,68 @@ +//===--- CodeGenModule.cpp - Emit LLVM Code from ASTs for a Module --------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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/TargetInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Intrinsics.h" +using namespace clang; +using namespace CodeGen; + + +CodeGenModule::CodeGenModule(ASTContext &C, llvm::Module &M) + : Context(C), TheModule(M), Types(C.Target) {} + +llvm::Constant *CodeGenModule::GetAddrOfGlobalDecl(const Decl *D) { + // See if it is already in the map. + llvm::Constant *&Entry = GlobalDeclMap[D]; + if (Entry) return Entry; + + QualType ASTTy = cast<ValueDecl>(D)->getType(); + const llvm::Type *Ty = getTypes().ConvertType(ASTTy); + if (isa<FunctionDecl>(D)) { + const llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty); + // FIXME: param attributes for sext/zext etc. + return Entry = new llvm::Function(FTy, llvm::Function::ExternalLinkage, + D->getName(), &getModule()); + } + + assert(isa<FileVarDecl>(D) && "Unknown global decl!"); + + return Entry = new llvm::GlobalVariable(Ty, false, + llvm::GlobalValue::ExternalLinkage, + 0, D->getName(), &getModule()); +} + +void CodeGenModule::EmitFunction(FunctionDecl *FD) { + // If this is not a prototype, emit the body. + if (FD->getBody()) + CodeGenFunction(*this).GenerateCode(FD); +} + + + +llvm::Function *CodeGenModule::getMemCpyFn() { + if (MemCpyFn) return MemCpyFn; + llvm::Intrinsic::ID IID; + switch (Context.Target.getPointerWidth(SourceLocation())) { + default: assert(0 && "Unknown ptr width"); + case 32: IID = llvm::Intrinsic::memcpy_i32; break; + case 64: IID = llvm::Intrinsic::memcpy_i64; break; + } + return MemCpyFn = llvm::Intrinsic::getDeclaration(&TheModule, IID); +} diff --git a/CodeGen/CodeGenModule.h b/CodeGen/CodeGenModule.h new file mode 100644 index 0000000000..885fb97a9f --- /dev/null +++ b/CodeGen/CodeGenModule.h @@ -0,0 +1,60 @@ +//===--- CodeGenModule.h - Per-Module state for LLVM CodeGen --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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 CODEGEN_CODEGENMODULE_H +#define CODEGEN_CODEGENMODULE_H + +#include "CodeGenTypes.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + class Module; + class Constant; + class Function; +} + +namespace clang { + class ASTContext; + class FunctionDecl; + class Decl; + +namespace CodeGen { + +/// CodeGenModule - This class organizes the cross-module state that is used +/// while generating LLVM code. +class CodeGenModule { + ASTContext &Context; + llvm::Module &TheModule; + CodeGenTypes Types; + + llvm::Function *MemCpyFn; + llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap; +public: + CodeGenModule(ASTContext &C, llvm::Module &M); + + ASTContext &getContext() const { return Context; } + llvm::Module &getModule() const { return TheModule; } + CodeGenTypes &getTypes() { return Types; } + + llvm::Constant *GetAddrOfGlobalDecl(const Decl *D); + + llvm::Function *getMemCpyFn(); + + void EmitFunction(FunctionDecl *FD); + + void PrintStats() {} +}; +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp new file mode 100644 index 0000000000..f0b77908be --- /dev/null +++ b/CodeGen/CodeGenTypes.cpp @@ -0,0 +1,151 @@ +//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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" + +using namespace clang; +using namespace CodeGen; + + +/// ConvertType - Convert the specified type to its LLVM form. +const llvm::Type *CodeGenTypes::ConvertType(QualType T) { + // FIXME: Cache these, move the CodeGenModule, expand, etc. + const clang::Type &Ty = *T.getCanonicalType(); + + switch (Ty.getTypeClass()) { + 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. + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + return llvm::IntegerType::get(Target.getCharWidth(SourceLocation())); + + case BuiltinType::Bool: + // FIXME: This is very strange. We want scalars to be i1, but in memory + // they can be i1 or i32. Should the codegen handle this issue? + return llvm::Type::Int1Ty; + + case BuiltinType::Short: + case BuiltinType::UShort: + return llvm::IntegerType::get(Target.getShortWidth(SourceLocation())); + + case BuiltinType::Int: + case BuiltinType::UInt: + return llvm::IntegerType::get(Target.getIntWidth(SourceLocation())); + + case BuiltinType::Long: + case BuiltinType::ULong: + return llvm::IntegerType::get(Target.getLongWidth(SourceLocation())); + + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + return llvm::IntegerType::get(Target.getLongLongWidth(SourceLocation())); + + 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); + return llvm::PointerType::get(ConvertType(P.getPointeeType())); + } + case Type::Reference: { + const ReferenceType &R = cast<ReferenceType>(Ty); + return llvm::PointerType::get(ConvertType(R.getReferenceeType())); + } + + case Type::Array: { + const ArrayType &A = cast<ArrayType>(Ty); + assert(A.getSizeModifier() == ArrayType::Normal && + A.getIndexTypeQualifier() == 0 && + "FIXME: We only handle trivial array types so far!"); + + llvm::APSInt Size(32); + if (A.getSize() && A.getSize()->isIntegerConstantExpr(Size)) { + const llvm::Type *EltTy = ConvertType(A.getElementType()); + return llvm::ArrayType::get(EltTy, Size.getZExtValue()); + } else { + assert(0 && "FIXME: VLAs not implemented yet!"); + } + } + 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)); + 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, 0); + } + case Type::TypeName: + case Type::Tagged: + break; + } + + // 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 + ArgTys.push_back(llvm::PointerType::get(Ty)); + } +} + diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h new file mode 100644 index 0000000000..dd322a19ec --- /dev/null +++ b/CodeGen/CodeGenTypes.h @@ -0,0 +1,47 @@ +//===--- CodeGenTypes.h - Type translation for LLVM CodeGen -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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 CODEGEN_CODEGENTYPES_H +#define CODEGEN_CODEGENTYPES_H + +#include <vector> + +namespace llvm { + class Type; +} + +namespace clang { + class TargetInfo; + class QualType; + class FunctionTypeProto; + +namespace CodeGen { + +/// CodeGenTypes - This class organizes the cross-module state that is used +/// while lowering AST types to LLVM types. +class CodeGenTypes { + TargetInfo &Target; + +public: + CodeGenTypes(TargetInfo &target) : Target(target) {} + + TargetInfo &getTarget() const { return Target; } + + const llvm::Type *ConvertType(QualType T); + void DecodeArgumentTypes(const FunctionTypeProto &FTP, + std::vector<const llvm::Type*> &ArgTys); +}; +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/CodeGen/Makefile b/CodeGen/Makefile new file mode 100644 index 0000000000..5e6f705846 --- /dev/null +++ b/CodeGen/Makefile @@ -0,0 +1,23 @@ +##===- clang/CodeGen/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file was developed by Chris Lattner and 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/CodeGen/ModuleBuilder.cpp b/CodeGen/ModuleBuilder.cpp new file mode 100644 index 0000000000..16b13d1c4d --- /dev/null +++ b/CodeGen/ModuleBuilder.cpp @@ -0,0 +1,39 @@ +//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and 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" +using namespace clang; + + +/// Init - Create an ModuleBuilder with the specified ASTContext. +clang::CodeGen::BuilderTy * +clang::CodeGen::Init(ASTContext &Context, llvm::Module &M) { + return new CodeGenModule(Context, M); +} + +void clang::CodeGen::Terminate(BuilderTy *B) { + delete static_cast<CodeGenModule*>(B); +} + +/// CodeGenFunction - Convert the AST node for a FunctionDecl into LLVM. +/// +void clang::CodeGen::CodeGenFunction(BuilderTy *B, FunctionDecl *D) { + static_cast<CodeGenModule*>(B)->EmitFunction(D); +} + +/// PrintStats - Emit statistic information to stderr. +/// +void clang::CodeGen::PrintStats(BuilderTy *B) { + static_cast<CodeGenModule*>(B)->PrintStats(); +} |