blob: 0b30a99f3d26844436a2c6a75630bacd61089dcd [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 Lattnere47e4402007-06-01 18:02:12 +000047 }
48}
49
50void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) {
51 // FIXME: handle vla's etc.
52
53 for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end();
54 I != E; ++I)
55 EmitStmt(*I);
56}
57
58void CodeGenFunction::EmitBlock(BasicBlock *BB) {
59 // Emit a branch from this block to the next one if this was a real block. If
60 // this was just a fall-through block after a terminator, don't emit it.
61 BasicBlock *LastBB = Builder.GetInsertBlock();
62
63 if (LastBB->getTerminator()) {
64 // If the previous block is already terminated, don't touch it.
65 } else if (LastBB->empty() && LastBB->getValueName() == 0) {
66 // If the last block was an empty placeholder, remove it now.
67 // TODO: cache and reuse these.
68 Builder.GetInsertBlock()->eraseFromParent();
69 } else {
70 // Otherwise, create a fall-through branch.
71 Builder.CreateBr(BB);
72 }
73 CurFn->getBasicBlockList().push_back(BB);
74 Builder.SetInsertPoint(BB);
75}
76
77void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
78 llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
79
80 EmitBlock(NextBB);
81 EmitStmt(S.getSubStmt());
82}
83
84void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
85 Builder.CreateBr(getBasicBlockForLabel(S.getLabel()));
86
87 // Emit a block after the branch so that dead code after a goto has some place
88 // to go.
89 Builder.SetInsertPoint(new BasicBlock("", CurFn));
90}
91
92void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
93 // Emit the if condition.
94 ExprResult CondVal = EmitExpr(S.getCond());
95 QualType CondTy = S.getCond()->getType().getCanonicalType();
96
97 // C99 6.8.4.1: The first substatement is executed if the expression compares
98 // unequal to 0. The condition must be a scalar type.
99 llvm::Value *BoolCondVal;
100
101 // MOVE this to a helper method, to share with for/while, assign to bool, etc.
102 if (const BuiltinType *BT = dyn_cast<BuiltinType>(CondTy)) {
103 switch (BT->getKind()) {
104 default: assert(0 && "Unknown scalar value");
105 case BuiltinType::Bool:
106 BoolCondVal = CondVal.getVal();
107 // Bool is already evaluated right.
108 assert(BoolCondVal->getType() == llvm::Type::Int1Ty &&
109 "Unexpected bool value type!");
110 break;
111 case BuiltinType::Char:
112 case BuiltinType::SChar:
113 case BuiltinType::UChar:
114 case BuiltinType::Int:
115 case BuiltinType::UInt:
116 case BuiltinType::Long:
117 case BuiltinType::ULong:
118 case BuiltinType::LongLong:
119 case BuiltinType::ULongLong: {
120 // Compare against zero for integers.
121 BoolCondVal = CondVal.getVal();
122 llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
Chris Lattnerdb91b162007-06-02 00:16:28 +0000123 BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero, "tobool");
Chris Lattnere47e4402007-06-01 18:02:12 +0000124 break;
125 }
126 case BuiltinType::Float:
127 case BuiltinType::Double:
128 case BuiltinType::LongDouble: {
129 // Compare against 0.0 for fp scalars.
130 BoolCondVal = CondVal.getVal();
131 llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
132 // FIXME: llvm-gcc produces a une comparison: validate this is right.
Chris Lattnerdb91b162007-06-02 00:16:28 +0000133 BoolCondVal = Builder.CreateFCmpUNE(BoolCondVal, Zero, "tobool");
Chris Lattnere47e4402007-06-01 18:02:12 +0000134 break;
135 }
136
137 case BuiltinType::FloatComplex:
138 case BuiltinType::DoubleComplex:
139 case BuiltinType::LongDoubleComplex:
140 assert(0 && "comparisons against complex not implemented yet");
141 }
142 } else if (isa<PointerType>(CondTy)) {
143 BoolCondVal = CondVal.getVal();
144 llvm::Value *NullPtr = Constant::getNullValue(BoolCondVal->getType());
Chris Lattnerdb91b162007-06-02 00:16:28 +0000145 BoolCondVal = Builder.CreateICmpNE(BoolCondVal, NullPtr, "tobool");
Chris Lattnere47e4402007-06-01 18:02:12 +0000146
147 } else {
148 const TagType *TT = cast<TagType>(CondTy);
149 assert(TT->getDecl()->getKind() == Decl::Enum && "Unknown scalar type");
150 // Compare against zero.
151 BoolCondVal = CondVal.getVal();
152 llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
Chris Lattnerdb91b162007-06-02 00:16:28 +0000153 BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero, "tobool");
Chris Lattnere47e4402007-06-01 18:02:12 +0000154 }
155
156 BasicBlock *ContBlock = new BasicBlock("ifend");
157 BasicBlock *ThenBlock = new BasicBlock("ifthen");
158 BasicBlock *ElseBlock = ContBlock;
159
160 if (S.getElse())
161 ElseBlock = new BasicBlock("ifelse");
162
163 // Insert the conditional branch.
164 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
165
166 // Emit the 'then' code.
167 EmitBlock(ThenBlock);
168 EmitStmt(S.getThen());
169 Builder.CreateBr(ContBlock);
170
171 // Emit the 'else' code if present.
172 if (const Stmt *Else = S.getElse()) {
173 EmitBlock(ElseBlock);
174 EmitStmt(Else);
175 Builder.CreateBr(ContBlock);
176 }
177
178 // Emit the continuation block for code after the if.
179 EmitBlock(ContBlock);
180}
181
Chris Lattner3f3dbee2007-06-02 03:19:07 +0000182/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
183/// if the function returns void, or may be missing one if the function returns
184/// non-void. Fun stuff :).
185void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
186 ExprResult RetVal;
187
188 // Emit the result value, even if unused, to evalute the side effects.
189 const Expr *RV = S.getRetValue();
190 if (RV)
191 RetVal = EmitExpr(RV);
192
193 if (CurFuncDecl->getType()->isVoidType()) {
194 // If the function returns void, emit ret void, and ignore the retval.
195 Builder.CreateRetVoid();
196 } else if (RV == 0) {
197 // "return;" in a function that returns a value.
198 const llvm::Type *RetTy = CurFn->getFunctionType()->getReturnType();
199 if (RetTy == llvm::Type::VoidTy)
200 Builder.CreateRetVoid(); // struct return etc.
201 else
202 Builder.CreateRet(llvm::UndefValue::get(RetTy));
203 } else if (RetVal.isScalar()) {
204 // FIXME: return should coerce its operand to the return type!
205 Builder.CreateRet(RetVal.getVal());
206 } else {
207 assert(0 && "FIXME: aggregate return unimp");
208 }
209
210 // Emit a block after the branch so that dead code after a goto has some place
211 // to go.
212 Builder.SetInsertPoint(new BasicBlock("", CurFn));
213}
214