blob: 885ee41f36c4c92454631f77fe0ce12194d64b37 [file] [log] [blame]
Chris Lattnerbed31442007-05-28 01:07:47 +00001//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===//
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 coordinates the per-function state used while generating code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "CodeGenModule.h"
Chris Lattnerd1af2d22007-05-29 23:17:50 +000016#include "clang/Basic/TargetInfo.h"
17#include "clang/AST/AST.h"
Chris Lattner208ae962007-05-30 17:57:17 +000018#include "llvm/Constants.h"
Chris Lattnerd1af2d22007-05-29 23:17:50 +000019#include "llvm/DerivedTypes.h"
Chris Lattner308f4312007-05-29 23:50:05 +000020#include "llvm/Function.h"
Chris Lattnerbed31442007-05-28 01:07:47 +000021using namespace llvm;
22using namespace clang;
23using namespace CodeGen;
24
Chris Lattnerd1af2d22007-05-29 23:17:50 +000025CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
26 : CGM(cgm), Target(CGM.getContext().Target) {}
27
28
Chris Lattnerac248202007-05-30 00:13:02 +000029llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
30 BasicBlock *&BB = LabelMap[S];
31 if (BB) return BB;
32
33 // Create, but don't insert, the new block.
34 return BB = new BasicBlock(S->getName());
35}
36
37
Chris Lattnerd1af2d22007-05-29 23:17:50 +000038/// ConvertType - Convert the specified type to its LLVM form.
39const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
40 // FIXME: Cache these, move the CodeGenModule, expand, etc.
41 const clang::Type &Ty = *T.getCanonicalType();
42
43 switch (Ty.getTypeClass()) {
44 case Type::Builtin: {
45 switch (cast<BuiltinType>(Ty).getKind()) {
46 case BuiltinType::Void:
47 // LLVM void type can only be used as the result of a function call. Just
48 // map to the same as char.
49 case BuiltinType::Char:
50 case BuiltinType::SChar:
51 case BuiltinType::UChar:
52 return IntegerType::get(Target.getCharWidth(Loc));
53
54 case BuiltinType::Bool:
55 return IntegerType::get(Target.getBoolWidth(Loc));
56
57 case BuiltinType::Short:
58 case BuiltinType::UShort:
59 return IntegerType::get(Target.getShortWidth(Loc));
60
61 case BuiltinType::Int:
62 case BuiltinType::UInt:
63 return IntegerType::get(Target.getIntWidth(Loc));
64
65 case BuiltinType::Long:
66 case BuiltinType::ULong:
67 return IntegerType::get(Target.getLongWidth(Loc));
68
69 case BuiltinType::LongLong:
70 case BuiltinType::ULongLong:
71 return IntegerType::get(Target.getLongLongWidth(Loc));
72
73 case BuiltinType::Float: return llvm::Type::FloatTy;
74 case BuiltinType::Double: return llvm::Type::DoubleTy;
75 case BuiltinType::LongDouble:
76 case BuiltinType::FloatComplex:
77 case BuiltinType::DoubleComplex:
78 case BuiltinType::LongDoubleComplex:
79 ;
80 }
81 break;
82 }
83 case Type::Pointer:
84 case Type::Reference:
85 case Type::Array:
86 break;
87 case Type::FunctionNoProto:
88 case Type::FunctionProto: {
89 const FunctionType &FP = cast<FunctionType>(Ty);
90 const llvm::Type *ResultType;
91
92 if (FP.getResultType()->isVoidType())
93 ResultType = llvm::Type::VoidTy; // Result of function uses llvm void.
94 else
95 ResultType = ConvertType(FP.getResultType(), Loc);
96
97 // FIXME: Convert argument types.
98
99 return llvm::FunctionType::get(ResultType,
100 std::vector<const llvm::Type*>(),
101 false,
102 0);
103 }
104 case Type::TypeName:
105 case Type::Tagged:
106 break;
107 }
108
109 // FIXME: implement.
110 return OpaqueType::get();
111}
112
113
Chris Lattner308f4312007-05-29 23:50:05 +0000114void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
Chris Lattnerd1af2d22007-05-29 23:17:50 +0000115 const llvm::Type *Ty = ConvertType(FD->getType(), FD->getLocation());
116
Chris Lattnerac248202007-05-30 00:13:02 +0000117 CurFn = new Function(cast<llvm::FunctionType>(Ty),
118 Function::ExternalLinkage,
119 FD->getName(), &CGM.getModule());
Chris Lattnerd1af2d22007-05-29 23:17:50 +0000120
Chris Lattnerac248202007-05-30 00:13:02 +0000121 BasicBlock *EntryBB = new BasicBlock("entry", CurFn);
Chris Lattner308f4312007-05-29 23:50:05 +0000122
123 // TODO: Walk the decls, creating allocas etc.
124
125 Builder.SetInsertPoint(EntryBB);
126
127 EmitStmt(FD->getBody());
Chris Lattnerd1af2d22007-05-29 23:17:50 +0000128}
Chris Lattner308f4312007-05-29 23:50:05 +0000129
130
131//===----------------------------------------------------------------------===//
132// Statement Emission
133//===----------------------------------------------------------------------===//
134
135void CodeGenFunction::EmitStmt(const Stmt *S) {
136 assert(S && "Null statement?");
137
138 switch (S->getStmtClass()) {
139 default:
Chris Lattner208ae962007-05-30 17:57:17 +0000140 // Must be an expression in a stmt context. Emit the value and ignore the
141 // result.
142 if (const Expr *E = dyn_cast<Expr>(S)) {
143 EmitExpr(E);
144 } else {
145 printf("Unimplemented stmt!\n");
146 S->dump();
147 }
Chris Lattner308f4312007-05-29 23:50:05 +0000148 break;
149 case Stmt::NullStmtClass: break;
150 case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
Chris Lattnerac248202007-05-30 00:13:02 +0000151 case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
152 case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
Chris Lattner308f4312007-05-29 23:50:05 +0000153 }
154}
155
156void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) {
157 // FIXME: handle vla's etc.
158
159 for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end();
160 I != E; ++I)
161 EmitStmt(*I);
162}
163
Chris Lattnerac248202007-05-30 00:13:02 +0000164void CodeGenFunction::EmitBlock(BasicBlock *BB) {
165 // Emit a branch from this block to the next one if this was a real block. If
166 // this was just a fall-through block after a terminator, don't emit it.
167 if (!Builder.GetInsertBlock()->empty() ||
168 Builder.GetInsertBlock()->getValueName()) {
169 Builder.CreateBr(BB);
170 } else {
171 // TODO: cache and reuse these.
172 Builder.GetInsertBlock()->eraseFromParent();
173 }
174 CurFn->getBasicBlockList().push_back(BB);
175 Builder.SetInsertPoint(BB);
176}
177
178void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
179 llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
180
181 EmitBlock(NextBB);
182}
183
184void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
185 Builder.CreateBr(getBasicBlockForLabel(S.getLabel()));
186
187 Builder.SetInsertPoint(new BasicBlock("", CurFn));
188}
189
Chris Lattner208ae962007-05-30 17:57:17 +0000190
191
192//===--------------------------------------------------------------------===//
193// Expression Emission
194//===--------------------------------------------------------------------===//
195
196ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
197 assert(E && "Null expression?");
198
199 switch (E->getStmtClass()) {
200 default:
201 printf("Unimplemented expr!\n");
202 E->dump();
203 return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
204 case Stmt::IntegerLiteralClass:
205 return EmitIntegerLiteral(cast<IntegerLiteral>(E));
206 }
207
208}
209
210ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
211 return ExprResult::get(ConstantInt::get(E->getValue()));
212}
213
214