forked from OSchip/llvm-project
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:
parent
be31ed8e88
commit
f0106d2578
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue