Refactor EvaluateScalarValueToBool out of if statement emission, so it can

be shared.

Implement infrastructure for unary operator emission.

Implement basic logical not support.  We now compile:

  register short X;

  if (!X) {

into:

        %tmp = load i16* %X             ; <i16> [#uses=1]
        %tobool = icmp ne i16 %tmp, 0           ; <i1> [#uses=1]
        %lnot = xor i1 %tobool, true            ; <i1> [#uses=1]
        zext i1 %lnot to i32            ; <i32>:0 [#uses=1]
        %tobool1 = icmp ne i32 %0, 0            ; <i1> [#uses=1]
        br i1 %tobool1, label %ifthen, label %ifend

llvm-svn: 39559
This commit is contained in:
Chris Lattner 2007-06-02 19:33:17 +00:00
parent be31ed8e88
commit f0106d2578
4 changed files with 131 additions and 77 deletions

View File

@ -19,6 +19,66 @@ using namespace llvm;
using namespace clang;
using namespace CodeGen;
//===--------------------------------------------------------------------===//
// Miscellaneous Helper Methods
//===--------------------------------------------------------------------===//
/// EvaluateScalarValueToBool - Evaluate the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val == 0".
Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) {
Ty = Ty.getCanonicalType();
Value *Result;
if (const BuiltinType *BT = dyn_cast<BuiltinType>(Ty)) {
switch (BT->getKind()) {
default: assert(0 && "Unknown scalar value");
case BuiltinType::Bool:
Result = Val.getVal();
// Bool is already evaluated right.
assert(Result->getType() == llvm::Type::Int1Ty &&
"Unexpected bool value type!");
return Result;
case BuiltinType::Char:
case BuiltinType::SChar:
case BuiltinType::UChar:
case BuiltinType::Short:
case BuiltinType::UShort:
case BuiltinType::Int:
case BuiltinType::UInt:
case BuiltinType::Long:
case BuiltinType::ULong:
case BuiltinType::LongLong:
case BuiltinType::ULongLong:
// Code below handles simple integers.
break;
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble: {
// Compare against 0.0 for fp scalars.
Result = Val.getVal();
llvm::Value *Zero = Constant::getNullValue(Result->getType());
// FIXME: llvm-gcc produces a une comparison: validate this is right.
Result = Builder.CreateFCmpUNE(Result, Zero, "tobool");
return Result;
}
case BuiltinType::FloatComplex:
case BuiltinType::DoubleComplex:
case BuiltinType::LongDoubleComplex:
assert(0 && "comparisons against complex not implemented yet");
}
} else {
assert((isa<PointerType>(Ty) ||
cast<TagType>(Ty)->getDecl()->getKind() == Decl::Enum) &&
"Unknown scalar type");
// Code below handles this fine.
}
// Usual case for integers, pointers, and enums: compare against zero.
Result = Val.getVal();
llvm::Value *Zero = Constant::getNullValue(Result->getType());
return Builder.CreateICmpNE(Result, Zero, "tobool");
}
//===--------------------------------------------------------------------===//
// LValue Expression Emission
//===--------------------------------------------------------------------===//
@ -75,6 +135,8 @@ ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
// Operators.
case Expr::ParenExprClass:
return EmitExpr(cast<ParenExpr>(E)->getSubExpr());
case Expr::UnaryOperatorClass:
return EmitUnaryOperator(cast<UnaryOperator>(E));
case Expr::BinaryOperatorClass:
return EmitBinaryOperator(cast<BinaryOperator>(E));
}
@ -85,6 +147,37 @@ ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
return ExprResult::get(ConstantInt::get(E->getValue()));
}
//===--------------------------------------------------------------------===//
// Unary Operator Emission
//===--------------------------------------------------------------------===//
ExprResult CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) {
switch (E->getOpcode()) {
default:
printf("Unimplemented unary expr!\n");
E->dump();
return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
case UnaryOperator::LNot: return EmitUnaryLNot(E);
}
}
/// C99 6.5.3.3
ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
ExprResult Op = EmitExpr(E->getSubExpr());
//UsualUnary();
// Compare to zero.
Value *BoolVal = EvaluateScalarValueToBool(Op, E->getSubExpr()->getType());
// Invert value.
BoolVal = Builder.CreateNot(BoolVal, "lnot");
// ZExt result to int.
const llvm::Type *ResTy = ConvertType(E->getType(), E->getOperatorLoc());
return ExprResult::get(Builder.CreateZExt(BoolVal, ResTy, "lnot.ext"));
}
//===--------------------------------------------------------------------===//
// Binary Operator Emission

View File

@ -97,62 +97,8 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// 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, "tobool");
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, "tobool");
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, "tobool");
} 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, "tobool");
}
llvm::Value *BoolCondVal =
EvaluateScalarValueToBool(CondVal, S.getCond()->getType());
BasicBlock *ContBlock = new BasicBlock("ifend");
BasicBlock *ThenBlock = new BasicBlock("ifthen");

View File

@ -38,6 +38,7 @@ namespace clang {
class Expr;
class DeclRefExpr;
class IntegerLiteral;
class UnaryOperator;
class BinaryOperator;
class BlockVarDecl;
@ -125,6 +126,8 @@ class CodeGenFunction {
/// LabelMap - This keeps track of the LLVM basic block for each C label.
DenseMap<const LabelStmt*, llvm::BasicBlock*> LabelMap;
const llvm::Type *LLVMIntTy;
public:
CodeGenFunction(CodeGenModule &cgm);
@ -141,6 +144,10 @@ public:
void EmitBlock(BasicBlock *BB);
/// EvaluateScalarValueToBool - Evaluate the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val == 0".
Value *EvaluateScalarValueToBool(ExprResult Val, QualType Ty);
//===--------------------------------------------------------------------===//
// Local Declaration Emission
//===--------------------------------------------------------------------===//
@ -174,13 +181,17 @@ public:
ExprResult EmitExpr(const Expr *E);
ExprResult EmitIntegerLiteral(const IntegerLiteral *E);
ExprResult EmitBinaryOperator(const BinaryOperator *E);
void EmitUsualArithmeticConversions(const BinaryOperator *E,
ExprResult &LHS, ExprResult &RHS);
// Unary Operators.
ExprResult EmitUnaryOperator(const UnaryOperator *E);
ExprResult EmitUnaryLNot(const UnaryOperator *E);
// Binary Operators.
ExprResult EmitBinaryOperator(const BinaryOperator *E);
ExprResult EmitBinaryAdd(const BinaryOperator *E);
};
} // end namespace CodeGen

View File

@ -236,46 +236,50 @@ public:
Real, Imag, // "__real expr"/"__imag expr" Extension.
Extension // __extension__ marker.
};
private:
Expr *Val;
Opcode Opc;
SourceLocation Loc;
public:
UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
: Expr(UnaryOperatorClass, type), Val(input), Opc(opc), Loc(l) {}
Opcode getOpcode() const { return Opc; }
Expr *getSubExpr() const { return Val; }
/// getOperatorLoc - Return the location of the operator.
SourceLocation getOperatorLoc() const { return Loc; }
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op);
bool isPostfix() const { return isPostfix(Opc); }
bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; }
static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
/// getDecl - a recursive routine that derives the base decl for an
/// expression. For example, it will return the declaration for "s" from
/// the following complex expression "s.zz[2].bb.vv".
static bool isAddressable(Expr *e);
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
static const char *getOpcodeStr(Opcode Op);
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op);
static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
Opcode getOpcode() const { return Opc; }
Expr *getSubExpr() const { return Val; }
virtual SourceRange getSourceRange() const {
if (isPostfix())
return SourceRange(Val->getLocStart(), Loc);
else
return SourceRange(Loc, Val->getLocEnd());
}
bool isPostfix() const { return isPostfix(Opc); }
bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; }
/// getDecl - a recursive routine that derives the base decl for an
/// expression. For example, it will return the declaration for "s" from
/// the following complex expression "s.zz[2].bb.vv".
static bool isAddressable(Expr *e);
virtual void visit(StmtVisitor &Visitor);
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryOperatorClass;
}
static bool classof(const UnaryOperator *) { return true; }
private:
Expr *Val;
Opcode Opc;
SourceLocation Loc;
};
/// SizeOfAlignOfTypeExpr - [C99 6.5.3.4] - This is only for sizeof/alignof of