blob: 6332f3ecd5fe68b5d3a94a96bb515656b1e2115d [file] [log] [blame]
Chris Lattnere47e4402007-06-01 18:02:12 +00001//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code to emit Stmt nodes as LLVM code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "clang/AST/AST.h"
16#include "llvm/Constants.h"
17#include "llvm/DerivedTypes.h"
18#include "llvm/Function.h"
19using namespace llvm;
20using namespace clang;
21using namespace CodeGen;
22
23//===----------------------------------------------------------------------===//
24// Statement Emission
25//===----------------------------------------------------------------------===//
26
27void CodeGenFunction::EmitStmt(const Stmt *S) {
28 assert(S && "Null statement?");
29
30 switch (S->getStmtClass()) {
31 default:
32 // Must be an expression in a stmt context. Emit the value and ignore the
33 // result.
34 if (const Expr *E = dyn_cast<Expr>(S)) {
35 EmitExpr(E);
36 } else {
37 printf("Unimplemented stmt!\n");
38 S->dump();
39 }
40 break;
41 case Stmt::NullStmtClass: break;
42 case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
43 case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
44 case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
45 case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
Chris Lattner3f3dbee2007-06-02 03:19:07 +000046 case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
Chris Lattner84915fa2007-06-02 04:16:21 +000047 case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
Chris Lattnere47e4402007-06-01 18:02:12 +000048 }
49}
50
51void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) {
52 // FIXME: handle vla's etc.
53
54 for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end();
55 I != E; ++I)
56 EmitStmt(*I);
57}
58
59void CodeGenFunction::EmitBlock(BasicBlock *BB) {
60 // Emit a branch from this block to the next one if this was a real block. If
61 // this was just a fall-through block after a terminator, don't emit it.
62 BasicBlock *LastBB = Builder.GetInsertBlock();
63
64 if (LastBB->getTerminator()) {
65 // If the previous block is already terminated, don't touch it.
66 } else if (LastBB->empty() && LastBB->getValueName() == 0) {
67 // If the last block was an empty placeholder, remove it now.
68 // TODO: cache and reuse these.
69 Builder.GetInsertBlock()->eraseFromParent();
70 } else {
71 // Otherwise, create a fall-through branch.
72 Builder.CreateBr(BB);
73 }
74 CurFn->getBasicBlockList().push_back(BB);
75 Builder.SetInsertPoint(BB);
76}
77
78void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
79 llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
80
81 EmitBlock(NextBB);
82 EmitStmt(S.getSubStmt());
83}
84
85void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
86 Builder.CreateBr(getBasicBlockForLabel(S.getLabel()));
87
88 // Emit a block after the branch so that dead code after a goto has some place
89 // to go.
90 Builder.SetInsertPoint(new BasicBlock("", CurFn));
91}
92
93void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
94 // Emit the if condition.
95 ExprResult CondVal = EmitExpr(S.getCond());
96 QualType CondTy = S.getCond()->getType().getCanonicalType();
97
98 // C99 6.8.4.1: The first substatement is executed if the expression compares
99 // unequal to 0. The condition must be a scalar type.
Chris Lattnerf0106d22007-06-02 19:33:17 +0000100 llvm::Value *BoolCondVal =
101 EvaluateScalarValueToBool(CondVal, S.getCond()->getType());
Chris Lattnere47e4402007-06-01 18:02:12 +0000102
103 BasicBlock *ContBlock = new BasicBlock("ifend");
104 BasicBlock *ThenBlock = new BasicBlock("ifthen");
105 BasicBlock *ElseBlock = ContBlock;
106
107 if (S.getElse())
108 ElseBlock = new BasicBlock("ifelse");
109
110 // Insert the conditional branch.
111 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
112
113 // Emit the 'then' code.
114 EmitBlock(ThenBlock);
115 EmitStmt(S.getThen());
116 Builder.CreateBr(ContBlock);
117
118 // Emit the 'else' code if present.
119 if (const Stmt *Else = S.getElse()) {
120 EmitBlock(ElseBlock);
121 EmitStmt(Else);
122 Builder.CreateBr(ContBlock);
123 }
124
125 // Emit the continuation block for code after the if.
126 EmitBlock(ContBlock);
127}
128
Chris Lattner3f3dbee2007-06-02 03:19:07 +0000129/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
130/// if the function returns void, or may be missing one if the function returns
131/// non-void. Fun stuff :).
132void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
133 ExprResult RetVal;
134
135 // Emit the result value, even if unused, to evalute the side effects.
136 const Expr *RV = S.getRetValue();
137 if (RV)
138 RetVal = EmitExpr(RV);
139
140 if (CurFuncDecl->getType()->isVoidType()) {
141 // If the function returns void, emit ret void, and ignore the retval.
142 Builder.CreateRetVoid();
143 } else if (RV == 0) {
144 // "return;" in a function that returns a value.
145 const llvm::Type *RetTy = CurFn->getFunctionType()->getReturnType();
146 if (RetTy == llvm::Type::VoidTy)
147 Builder.CreateRetVoid(); // struct return etc.
148 else
149 Builder.CreateRet(llvm::UndefValue::get(RetTy));
150 } else if (RetVal.isScalar()) {
151 // FIXME: return should coerce its operand to the return type!
152 Builder.CreateRet(RetVal.getVal());
153 } else {
154 assert(0 && "FIXME: aggregate return unimp");
155 }
156
157 // Emit a block after the branch so that dead code after a goto has some place
158 // to go.
159 Builder.SetInsertPoint(new BasicBlock("", CurFn));
160}
161