forked from OSchip/llvm-project
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:
parent
b2e723bed4
commit
5269c0377c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue