//===--- 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 llvm; using namespace clang; using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : CGM(cgm), Target(CGM.getContext().Target) {} llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) { BasicBlock *&BB = LabelMap[S]; if (BB) return BB; // Create, but don't insert, the new block. return BB = new BasicBlock(S->getName()); } /// ConvertType - Convert the specified type to its LLVM form. const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) { // FIXME: Cache these, move the CodeGenModule, expand, etc. const clang::Type &Ty = *T.getCanonicalType(); switch (Ty.getTypeClass()) { case Type::Builtin: { switch (cast(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: case BuiltinType::SChar: case BuiltinType::UChar: return IntegerType::get(Target.getCharWidth(Loc)); case BuiltinType::Bool: return IntegerType::get(Target.getBoolWidth(Loc)); case BuiltinType::Short: case BuiltinType::UShort: return IntegerType::get(Target.getShortWidth(Loc)); case BuiltinType::Int: case BuiltinType::UInt: return IntegerType::get(Target.getIntWidth(Loc)); case BuiltinType::Long: case BuiltinType::ULong: return IntegerType::get(Target.getLongWidth(Loc)); case BuiltinType::LongLong: case BuiltinType::ULongLong: return IntegerType::get(Target.getLongLongWidth(Loc)); case BuiltinType::Float: return llvm::Type::FloatTy; case BuiltinType::Double: return llvm::Type::DoubleTy; case BuiltinType::LongDouble: case BuiltinType::FloatComplex: case BuiltinType::DoubleComplex: case BuiltinType::LongDoubleComplex: ; } break; } case Type::Pointer: case Type::Reference: case Type::Array: break; case Type::FunctionNoProto: case Type::FunctionProto: { const FunctionType &FP = cast(Ty); const llvm::Type *ResultType; if (FP.getResultType()->isVoidType()) ResultType = llvm::Type::VoidTy; // Result of function uses llvm void. else ResultType = ConvertType(FP.getResultType(), Loc); // FIXME: Convert argument types. return llvm::FunctionType::get(ResultType, std::vector(), false, 0); } case Type::TypeName: case Type::Tagged: break; } // FIXME: implement. return OpaqueType::get(); } void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { const llvm::Type *Ty = ConvertType(FD->getType(), FD->getLocation()); CurFn = new Function(cast(Ty), Function::ExternalLinkage, FD->getName(), &CGM.getModule()); BasicBlock *EntryBB = new BasicBlock("entry", CurFn); // TODO: Walk the decls, creating allocas etc. Builder.SetInsertPoint(EntryBB); EmitStmt(FD->getBody()); // Emit a simple return for now. Builder.CreateRetVoid(); // Verify that the function is well formed. assert(!verifyFunction(*CurFn)); } //===----------------------------------------------------------------------===// // 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(S)) { EmitExpr(E); } else { printf("Unimplemented stmt!\n"); S->dump(); } break; case Stmt::NullStmtClass: break; case Stmt::CompoundStmtClass: EmitCompoundStmt(cast(*S)); break; case Stmt::LabelStmtClass: EmitLabelStmt(cast(*S)); break; case Stmt::GotoStmtClass: EmitGotoStmt(cast(*S)); break; case Stmt::IfStmtClass: EmitIfStmt(cast(*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(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. 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 BasicBlock("", CurFn)); } void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // Emit the if condition. ExprResult CondVal = EmitExpr(S.getCond()); QualType CondTy = S.getCond()->getType().getCanonicalType(); // 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; // MOVE this to a helper method, to share with for/while, assign to bool, etc. if (const BuiltinType *BT = dyn_cast(CondTy)) { switch (BT->getKind()) { default: assert(0 && "Unknown scalar value"); case BuiltinType::Bool: BoolCondVal = CondVal.getVal(); // Bool is already evaluated right. assert(BoolCondVal->getType() == llvm::Type::Int1Ty && "Unexpected bool value type!"); break; case BuiltinType::Char: case BuiltinType::SChar: case BuiltinType::UChar: case BuiltinType::Int: case BuiltinType::UInt: case BuiltinType::Long: case BuiltinType::ULong: case BuiltinType::LongLong: case BuiltinType::ULongLong: { // Compare against zero for integers. BoolCondVal = CondVal.getVal(); llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType()); BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero); break; } case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: { // Compare against 0.0 for fp scalars. BoolCondVal = CondVal.getVal(); llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType()); // FIXME: llvm-gcc produces a une comparison: validate this is right. BoolCondVal = Builder.CreateFCmpUNE(BoolCondVal, Zero); break; } case BuiltinType::FloatComplex: case BuiltinType::DoubleComplex: case BuiltinType::LongDoubleComplex: assert(0 && "comparisons against complex not implemented yet"); } } else if (isa(CondTy)) { BoolCondVal = CondVal.getVal(); llvm::Value *NullPtr = Constant::getNullValue(BoolCondVal->getType()); BoolCondVal = Builder.CreateICmpNE(BoolCondVal, NullPtr); } else { const TagType *TT = cast(CondTy); assert(TT->getDecl()->getKind() == Decl::Enum && "Unknown scalar type"); // Compare against zero. BoolCondVal = CondVal.getVal(); llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType()); BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero); } BasicBlock *ContBlock = new BasicBlock("ifend"); BasicBlock *ThenBlock = new BasicBlock("ifthen"); BasicBlock *ElseBlock = ContBlock; if (S.getElse()) ElseBlock = new 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); } //===--------------------------------------------------------------------===// // Expression Emission //===--------------------------------------------------------------------===// ExprResult CodeGenFunction::EmitExpr(const Expr *E) { assert(E && "Null expression?"); switch (E->getStmtClass()) { default: printf("Unimplemented expr!\n"); E->dump(); return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty)); case Stmt::ParenExprClass: return EmitExpr(cast(E)->getSubExpr()); case Stmt::IntegerLiteralClass: return EmitIntegerLiteral(cast(E)); } } ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) { return ExprResult::get(ConstantInt::get(E->getValue())); }