diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/CodeGen/CGStmt.cpp | 34 | ||||
-rw-r--r-- | clang/CodeGen/CodeGenFunction.cpp | 1 | ||||
-rw-r--r-- | clang/CodeGen/CodeGenFunction.h | 4 |
3 files changed, 39 insertions, 0 deletions
diff --git a/clang/CodeGen/CGStmt.cpp b/clang/CodeGen/CGStmt.cpp index c8f02a12b98..0b30a99f3d2 100644 --- a/clang/CodeGen/CGStmt.cpp +++ b/clang/CodeGen/CGStmt.cpp @@ -43,6 +43,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { 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::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break; } } @@ -178,3 +179,36 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { EmitBlock(ContBlock); } +/// 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) { + ExprResult RetVal; + + // Emit the result value, even if unused, to evalute the side effects. + const Expr *RV = S.getRetValue(); + if (RV) + RetVal = EmitExpr(RV); + + if (CurFuncDecl->getType()->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 if (RetVal.isScalar()) { + // FIXME: return should coerce its operand to the return type! + Builder.CreateRet(RetVal.getVal()); + } else { + assert(0 && "FIXME: aggregate return unimp"); + } + + // Emit a block after the branch so that dead code after a goto has some place + // to go. + Builder.SetInsertPoint(new BasicBlock("", CurFn)); +} + diff --git a/clang/CodeGen/CodeGenFunction.cpp b/clang/CodeGen/CodeGenFunction.cpp index 6c7b714fb7f..c5c3f5256fe 100644 --- a/clang/CodeGen/CodeGenFunction.cpp +++ b/clang/CodeGen/CodeGenFunction.cpp @@ -116,6 +116,7 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { const llvm::FunctionType *Ty = cast<llvm::FunctionType>(ConvertType(FD->getType(), FD->getLocation())); + CurFuncDecl = FD; CurFn = new Function(Ty, Function::ExternalLinkage, FD->getName(), &CGM.getModule()); diff --git a/clang/CodeGen/CodeGenFunction.h b/clang/CodeGen/CodeGenFunction.h index 6e042d98658..fb7e72a9050 100644 --- a/clang/CodeGen/CodeGenFunction.h +++ b/clang/CodeGen/CodeGenFunction.h @@ -30,6 +30,7 @@ namespace clang { class LabelStmt; class GotoStmt; class IfStmt; + class ReturnStmt; class Expr; class IntegerLiteral; @@ -80,6 +81,8 @@ class CodeGenFunction { CodeGenModule &CGM; // Per-module state. TargetInfo &Target; LLVMBuilder Builder; + + const FunctionDecl *CurFuncDecl; llvm::Function *CurFn; /// LabelMap - This keeps track of the LLVM basic block for each C label. @@ -108,6 +111,7 @@ public: void EmitLabelStmt(const LabelStmt &S); void EmitGotoStmt(const GotoStmt &S); void EmitIfStmt(const IfStmt &S); + void EmitReturnStmt(const ReturnStmt &S); //===--------------------------------------------------------------------===// // Expression Emission |