mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-07 23:26:05 +00:00

void test() { goto l; l: if (11) { j: ; } } into: define void @test() { entry: br label %l l: ; preds = %entry icmp ne i32 11, 0 ; <i1>:0 [#uses=1] br i1 %0, label %ifthen, label %ifend ifthen: ; preds = %l br label %j j: ; preds = %ifthen br label %ifend ifend: ; preds = %j, %l } whoa... :) llvm-svn: 39533
315 lines
10 KiB
C++
315 lines
10 KiB
C++
//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This coordinates the per-function state used while generating code.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CodeGenFunction.h"
|
|
#include "CodeGenModule.h"
|
|
#include "clang/Basic/TargetInfo.h"
|
|
#include "clang/AST/AST.h"
|
|
#include "llvm/Constants.h"
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "llvm/Function.h"
|
|
using namespace llvm;
|
|
using namespace clang;
|
|
using namespace CodeGen;
|
|
|
|
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
|
: CGM(cgm), Target(CGM.getContext().Target) {}
|
|
|
|
|
|
llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
|
|
BasicBlock *&BB = LabelMap[S];
|
|
if (BB) return BB;
|
|
|
|
// Create, but don't insert, the new block.
|
|
return BB = new BasicBlock(S->getName());
|
|
}
|
|
|
|
|
|
/// ConvertType - Convert the specified type to its LLVM form.
|
|
const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
|
|
// FIXME: Cache these, move the CodeGenModule, expand, etc.
|
|
const clang::Type &Ty = *T.getCanonicalType();
|
|
|
|
switch (Ty.getTypeClass()) {
|
|
case Type::Builtin: {
|
|
switch (cast<BuiltinType>(Ty).getKind()) {
|
|
case BuiltinType::Void:
|
|
// LLVM void type can only be used as the result of a function call. Just
|
|
// map to the same as char.
|
|
case BuiltinType::Char:
|
|
case BuiltinType::SChar:
|
|
case BuiltinType::UChar:
|
|
return IntegerType::get(Target.getCharWidth(Loc));
|
|
|
|
case BuiltinType::Bool:
|
|
return IntegerType::get(Target.getBoolWidth(Loc));
|
|
|
|
case BuiltinType::Short:
|
|
case BuiltinType::UShort:
|
|
return IntegerType::get(Target.getShortWidth(Loc));
|
|
|
|
case BuiltinType::Int:
|
|
case BuiltinType::UInt:
|
|
return IntegerType::get(Target.getIntWidth(Loc));
|
|
|
|
case BuiltinType::Long:
|
|
case BuiltinType::ULong:
|
|
return IntegerType::get(Target.getLongWidth(Loc));
|
|
|
|
case BuiltinType::LongLong:
|
|
case BuiltinType::ULongLong:
|
|
return IntegerType::get(Target.getLongLongWidth(Loc));
|
|
|
|
case BuiltinType::Float: return llvm::Type::FloatTy;
|
|
case BuiltinType::Double: return llvm::Type::DoubleTy;
|
|
case BuiltinType::LongDouble:
|
|
case BuiltinType::FloatComplex:
|
|
case BuiltinType::DoubleComplex:
|
|
case BuiltinType::LongDoubleComplex:
|
|
;
|
|
}
|
|
break;
|
|
}
|
|
case Type::Pointer:
|
|
case Type::Reference:
|
|
case Type::Array:
|
|
break;
|
|
case Type::FunctionNoProto:
|
|
case Type::FunctionProto: {
|
|
const FunctionType &FP = cast<FunctionType>(Ty);
|
|
const llvm::Type *ResultType;
|
|
|
|
if (FP.getResultType()->isVoidType())
|
|
ResultType = llvm::Type::VoidTy; // Result of function uses llvm void.
|
|
else
|
|
ResultType = ConvertType(FP.getResultType(), Loc);
|
|
|
|
// FIXME: Convert argument types.
|
|
|
|
return llvm::FunctionType::get(ResultType,
|
|
std::vector<const llvm::Type*>(),
|
|
false,
|
|
0);
|
|
}
|
|
case Type::TypeName:
|
|
case Type::Tagged:
|
|
break;
|
|
}
|
|
|
|
// FIXME: implement.
|
|
return OpaqueType::get();
|
|
}
|
|
|
|
|
|
void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
|
const llvm::Type *Ty = ConvertType(FD->getType(), FD->getLocation());
|
|
|
|
CurFn = new Function(cast<llvm::FunctionType>(Ty),
|
|
Function::ExternalLinkage,
|
|
FD->getName(), &CGM.getModule());
|
|
|
|
BasicBlock *EntryBB = new BasicBlock("entry", CurFn);
|
|
|
|
// TODO: Walk the decls, creating allocas etc.
|
|
|
|
Builder.SetInsertPoint(EntryBB);
|
|
|
|
EmitStmt(FD->getBody());
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Statement Emission
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void CodeGenFunction::EmitStmt(const Stmt *S) {
|
|
assert(S && "Null statement?");
|
|
|
|
switch (S->getStmtClass()) {
|
|
default:
|
|
// Must be an expression in a stmt context. Emit the value and ignore the
|
|
// result.
|
|
if (const Expr *E = dyn_cast<Expr>(S)) {
|
|
EmitExpr(E);
|
|
} else {
|
|
printf("Unimplemented stmt!\n");
|
|
S->dump();
|
|
}
|
|
break;
|
|
case Stmt::NullStmtClass: break;
|
|
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
|
|
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
|
|
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
|
|
case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
|
|
}
|
|
}
|
|
|
|
void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) {
|
|
// FIXME: handle vla's etc.
|
|
|
|
for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end();
|
|
I != E; ++I)
|
|
EmitStmt(*I);
|
|
}
|
|
|
|
void CodeGenFunction::EmitBlock(BasicBlock *BB) {
|
|
// Emit a branch from this block to the next one if this was a real block. If
|
|
// this was just a fall-through block after a terminator, don't emit it.
|
|
BasicBlock *LastBB = Builder.GetInsertBlock();
|
|
|
|
if (LastBB->getTerminator()) {
|
|
// If the previous block is already terminated, don't touch it.
|
|
} else if (LastBB->empty() && LastBB->getValueName() == 0) {
|
|
// If the last block was an empty placeholder, remove it now.
|
|
// TODO: cache and reuse these.
|
|
Builder.GetInsertBlock()->eraseFromParent();
|
|
} else {
|
|
// Otherwise, create a fall-through branch.
|
|
Builder.CreateBr(BB);
|
|
}
|
|
CurFn->getBasicBlockList().push_back(BB);
|
|
Builder.SetInsertPoint(BB);
|
|
}
|
|
|
|
void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
|
|
llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
|
|
|
|
EmitBlock(NextBB);
|
|
EmitStmt(S.getSubStmt());
|
|
}
|
|
|
|
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
|
|
Builder.CreateBr(getBasicBlockForLabel(S.getLabel()));
|
|
|
|
// Emit a block after the branch so that dead code after a goto has some place
|
|
// to go.
|
|
Builder.SetInsertPoint(new BasicBlock("", CurFn));
|
|
}
|
|
|
|
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
|
|
// Emit the if condition.
|
|
ExprResult CondVal = EmitExpr(S.getCond());
|
|
QualType CondTy = S.getCond()->getType().getCanonicalType();
|
|
|
|
// C99 6.8.4.1: The first substatement is executed if the expression compares
|
|
// unequal to 0. The condition must be a scalar type.
|
|
llvm::Value *BoolCondVal;
|
|
|
|
// MOVE this to a helper method, to share with for/while, assign to bool, etc.
|
|
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CondTy)) {
|
|
switch (BT->getKind()) {
|
|
default: assert(0 && "Unknown scalar value");
|
|
case BuiltinType::Bool:
|
|
BoolCondVal = CondVal.getVal();
|
|
// Bool is already evaluated right.
|
|
assert(BoolCondVal->getType() == llvm::Type::Int1Ty &&
|
|
"Unexpected bool value type!");
|
|
break;
|
|
case BuiltinType::Char:
|
|
case BuiltinType::SChar:
|
|
case BuiltinType::UChar:
|
|
case BuiltinType::Int:
|
|
case BuiltinType::UInt:
|
|
case BuiltinType::Long:
|
|
case BuiltinType::ULong:
|
|
case BuiltinType::LongLong:
|
|
case BuiltinType::ULongLong: {
|
|
// Compare against zero for integers.
|
|
BoolCondVal = CondVal.getVal();
|
|
llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
|
|
BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero);
|
|
break;
|
|
}
|
|
case BuiltinType::Float:
|
|
case BuiltinType::Double:
|
|
case BuiltinType::LongDouble: {
|
|
// Compare against 0.0 for fp scalars.
|
|
BoolCondVal = CondVal.getVal();
|
|
llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
|
|
// FIXME: llvm-gcc produces a une comparison: validate this is right.
|
|
BoolCondVal = Builder.CreateFCmpUNE(BoolCondVal, Zero);
|
|
break;
|
|
}
|
|
|
|
case BuiltinType::FloatComplex:
|
|
case BuiltinType::DoubleComplex:
|
|
case BuiltinType::LongDoubleComplex:
|
|
assert(0 && "comparisons against complex not implemented yet");
|
|
}
|
|
} else if (isa<PointerType>(CondTy)) {
|
|
BoolCondVal = CondVal.getVal();
|
|
llvm::Value *NullPtr = Constant::getNullValue(BoolCondVal->getType());
|
|
BoolCondVal = Builder.CreateICmpNE(BoolCondVal, NullPtr);
|
|
|
|
} else {
|
|
const TagType *TT = cast<TagType>(CondTy);
|
|
assert(TT->getDecl()->getKind() == Decl::Enum && "Unknown scalar type");
|
|
// Compare against zero.
|
|
BoolCondVal = CondVal.getVal();
|
|
llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
|
|
BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero);
|
|
}
|
|
|
|
BasicBlock *ContBlock = new BasicBlock("ifend");
|
|
BasicBlock *ThenBlock = new BasicBlock("ifthen");
|
|
BasicBlock *ElseBlock = ContBlock;
|
|
|
|
if (S.getElse())
|
|
ElseBlock = new BasicBlock("ifelse");
|
|
|
|
// Insert the conditional branch.
|
|
Builder.CreateCondBr(BoolCondVal, ThenBlock, ElseBlock);
|
|
|
|
// Emit the 'then' code.
|
|
EmitBlock(ThenBlock);
|
|
EmitStmt(S.getThen());
|
|
Builder.CreateBr(ContBlock);
|
|
|
|
// Emit the 'else' code if present.
|
|
if (const Stmt *Else = S.getElse()) {
|
|
EmitBlock(ElseBlock);
|
|
EmitStmt(Else);
|
|
Builder.CreateBr(ContBlock);
|
|
}
|
|
|
|
// Emit the continuation block for code after the if.
|
|
EmitBlock(ContBlock);
|
|
}
|
|
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Expression Emission
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
|
|
assert(E && "Null expression?");
|
|
|
|
switch (E->getStmtClass()) {
|
|
default:
|
|
printf("Unimplemented expr!\n");
|
|
E->dump();
|
|
return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
|
|
case Stmt::ParenExprClass:
|
|
return EmitExpr(cast<ParenExpr>(E)->getSubExpr());
|
|
case Stmt::IntegerLiteralClass:
|
|
return EmitIntegerLiteral(cast<IntegerLiteral>(E));
|
|
}
|
|
|
|
}
|
|
|
|
ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
|
|
return ExprResult::get(ConstantInt::get(E->getValue()));
|
|
}
|
|
|
|
|