summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/CodeGen/CGStmt.cpp34
-rw-r--r--clang/CodeGen/CodeGenFunction.cpp1
-rw-r--r--clang/CodeGen/CodeGenFunction.h4
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
OpenPOWER on IntegriCloud