blob: 8e114a48e5b1c78f2c66a03ace6ce57b76fe3959 [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;
46 }
47}
48
49void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) {
50 // FIXME: handle vla's etc.
51
52 for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end();
53 I != E; ++I)
54 EmitStmt(*I);
55}
56
57void CodeGenFunction::EmitBlock(BasicBlock *BB) {
58 // Emit a branch from this block to the next one if this was a real block. If
59 // this was just a fall-through block after a terminator, don't emit it.
60 BasicBlock *LastBB = Builder.GetInsertBlock();
61
62 if (LastBB->getTerminator()) {
63 // If the previous block is already terminated, don't touch it.
64 } else if (LastBB->empty() && LastBB->getValueName() == 0) {
65 // If the last block was an empty placeholder, remove it now.
66 // TODO: cache and reuse these.
67 Builder.GetInsertBlock()->eraseFromParent();
68 } else {
69 // Otherwise, create a fall-through branch.
70 Builder.CreateBr(BB);
71 }
72 CurFn->getBasicBlockList().push_back(BB);
73 Builder.SetInsertPoint(BB);
74}
75
76void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
77 llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
78
79 EmitBlock(NextBB);
80 EmitStmt(S.getSubStmt());
81}
82
83void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
84 Builder.CreateBr(getBasicBlockForLabel(S.getLabel()));
85
86 // Emit a block after the branch so that dead code after a goto has some place
87 // to go.
88 Builder.SetInsertPoint(new BasicBlock("", CurFn));
89}
90
91void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
92 // Emit the if condition.
93 ExprResult CondVal = EmitExpr(S.getCond());
94 QualType CondTy = S.getCond()->getType().getCanonicalType();
95
96 // C99 6.8.4.1: The first substatement is executed if the expression compares
97 // unequal to 0. The condition must be a scalar type.
98 llvm::Value *BoolCondVal;
99
100 // MOVE this to a helper method, to share with for/while, assign to bool, etc.
101 if (const BuiltinType *BT = dyn_cast<BuiltinType>(CondTy)) {
102 switch (BT->getKind()) {
103 default: assert(0 && "Unknown scalar value");
104 case BuiltinType::Bool:
105 BoolCondVal = CondVal.getVal();
106 // Bool is already evaluated right.
107 assert(BoolCondVal->getType() == llvm::Type::Int1Ty &&
108 "Unexpected bool value type!");
109 break;
110 case BuiltinType::Char:
111 case BuiltinType::SChar:
112 case BuiltinType::UChar:
113 case BuiltinType::Int:
114 case BuiltinType::UInt:
115 case BuiltinType::Long:
116 case BuiltinType::ULong:
117 case BuiltinType::LongLong:
118 case BuiltinType::ULongLong: {
119 // Compare against zero for integers.
120 BoolCondVal = CondVal.getVal();
121 llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
122 BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero);
123 break;
124 }
125 case BuiltinType::Float:
126 case BuiltinType::Double:
127 case BuiltinType::LongDouble: {
128 // Compare against 0.0 for fp scalars.
129 BoolCondVal = CondVal.getVal();
130 llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
131 // FIXME: llvm-gcc produces a une comparison: validate this is right.
132 BoolCondVal = Builder.CreateFCmpUNE(BoolCondVal, Zero);
133 break;
134 }
135
136 case BuiltinType::FloatComplex:
137 case BuiltinType::DoubleComplex:
138 case BuiltinType::LongDoubleComplex:
139 assert(0 && "comparisons against complex not implemented yet");
140 }
141 } else if (isa<PointerType>(CondTy)) {
142 BoolCondVal = CondVal.getVal();
143 llvm::Value *NullPtr = Constant::getNullValue(BoolCondVal->getType());
144 BoolCondVal = Builder.CreateICmpNE(BoolCondVal, NullPtr);
145
146 } else {
147 const TagType *TT = cast<TagType>(CondTy);
148 assert(TT->getDecl()->getKind() == Decl::Enum && "Unknown scalar type");
149 // Compare against zero.
150 BoolCondVal = CondVal.getVal();
151 llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
152 BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero);
153 }
154
155 BasicBlock *ContBlock = new BasicBlock("ifend");
156 BasicBlock *ThenBlock = new BasicBlock("ifthen");
157 BasicBlock *ElseBlock = ContBlock;
158
159 if (S.getElse())
160 ElseBlock = new BasicBlock("ifelse");
161
162 // Insert the conditional branch.
163 Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
164
165 // Emit the 'then' code.
166 EmitBlock(ThenBlock);
167 EmitStmt(S.getThen());
168 Builder.CreateBr(ContBlock);
169
170 // Emit the 'else' code if present.
171 if (const Stmt *Else = S.getElse()) {
172 EmitBlock(ElseBlock);
173 EmitStmt(Else);
174 Builder.CreateBr(ContBlock);
175 }
176
177 // Emit the continuation block for code after the if.
178 EmitBlock(ContBlock);
179}
180