Add support for codegen'ing paren exprs and if stmts. We can now codegen:

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
This commit is contained in:
Chris Lattner 2007-05-30 21:03:58 +00:00
parent b2e723bed4
commit 5269c0377c
3 changed files with 128 additions and 10 deletions

View File

@ -150,6 +150,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
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;
}
}
@ -164,12 +165,17 @@ void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) {
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.
if (!Builder.GetInsertBlock()->empty() ||
Builder.GetInsertBlock()->getValueName()) {
Builder.CreateBr(BB);
} else {
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);
@ -179,14 +185,106 @@ 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);
}
//===--------------------------------------------------------------------===//
@ -201,6 +299,8 @@ ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
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));
}

View File

@ -29,6 +29,7 @@ namespace clang {
class CompoundStmt;
class LabelStmt;
class GotoStmt;
class IfStmt;
class Expr;
class IntegerLiteral;
@ -36,20 +37,36 @@ namespace clang {
namespace CodeGen {
class CodeGenModule;
struct ExprResult {
class ExprResult {
Value *V;
bool isAggregate;
bool IsAggregate;
public:
bool isAggregate() const { return IsAggregate; }
bool isScalar() const { return !IsAggregate; }
/// getVal() - Return the Value* of this scalar value.
Value *getVal() const {
assert(!isAggregate() && "Not a scalar!");
return V;
}
/// getAggregateVal() - Return the Value* of the address of the aggregate.
Value *getAggregateVal() const {
assert(isAggregate() && "Not an aggregate!");
return V;
}
static ExprResult get(Value *V) {
ExprResult ER;
ER.V = V;
ER.isAggregate = false;
ER.IsAggregate = false;
return ER;
}
static ExprResult getAggregate(Value *V) {
ExprResult ER;
ER.V = V;
ER.isAggregate = true;
ER.IsAggregate = true;
return ER;
}
};
@ -87,7 +104,7 @@ public:
void EmitCompoundStmt(const CompoundStmt &S);
void EmitLabelStmt(const LabelStmt &S);
void EmitGotoStmt(const GotoStmt &S);
void EmitIfStmt(const IfStmt &S);
//===--------------------------------------------------------------------===//
// Expression Emission

View File

@ -206,7 +206,8 @@ public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType()), L(l), R(r), Val(val) {}
Expr *getSubExpr() const { return Val; }
const Expr *getSubExpr() const { return Val; }
Expr *getSubExpr() { return Val; }
SourceRange getSourceRange() const { return SourceRange(L, R); }
virtual void visit(StmtVisitor &Visitor);