[cfe-commits] r39593 - in /cfe/cfe/trunk/CodeGen: CGExpr.cpp CGStmt.cpp CodeGenFunction.cpp CodeGenFunction.h
clattner at cs.uiuc.edu
clattner at cs.uiuc.edu
Wed Jul 11 09:46:02 PDT 2007
Author: clattner
Date: Wed Jul 11 11:46:02 2007
New Revision: 39593
URL: http://llvm.org/viewvc/llvm-project?rev=39593&view=rev
Log:
implement codegen of a bunch more loop constructs and most expressions
Modified:
cfe/cfe/trunk/CodeGen/CGExpr.cpp
cfe/cfe/trunk/CodeGen/CGStmt.cpp
cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp
cfe/cfe/trunk/CodeGen/CodeGenFunction.h
Modified: cfe/cfe/trunk/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CGExpr.cpp?rev=39593&r1=39592&r2=39593&view=diff
==============================================================================
--- cfe/cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGExpr.cpp Wed Jul 11 11:46:02 2007
@@ -23,9 +23,39 @@
// Miscellaneous Helper Methods
//===--------------------------------------------------------------------===//
-/// EvaluateScalarValueToBool - Evaluate the specified expression value to a
+
+/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
+/// expression and compare the result against zero, returning an Int1Ty value.
+Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
+ QualType Ty;
+ RValue Val = EmitExprWithUsualUnaryConversions(E, Ty);
+ return ConvertScalarValueToBool(Val, Ty);
+}
+
+//===--------------------------------------------------------------------===//
+// Conversions
+//===--------------------------------------------------------------------===//
+
+/// EmitConversion - Convert the value specied by Val, whose type is ValTy, to
+/// the type specified by DstTy, following the rules of C99 6.3.
+RValue CodeGenFunction::EmitConversion(RValue Val, QualType ValTy,
+ QualType DstTy) {
+ ValTy = ValTy.getCanonicalType();
+ DstTy = DstTy.getCanonicalType();
+ if (ValTy == DstTy) return Val;
+
+ if (const BuiltinType *DestBT = dyn_cast<BuiltinType>(DstTy)) {
+ if (DestBT->getKind() == BuiltinType::Bool)
+ return RValue::get(ConvertScalarValueToBool(Val, ValTy));
+ }
+
+ assert(0 && "FIXME: Unsupported conversion!");
+}
+
+
+/// ConvertScalarValueToBool - Convert the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val == 0".
-Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) {
+Value *CodeGenFunction::ConvertScalarValueToBool(RValue Val, QualType Ty) {
Ty = Ty.getCanonicalType();
Value *Result;
if (const BuiltinType *BT = dyn_cast<BuiltinType>(Ty)) {
@@ -96,19 +126,73 @@
// LValue Expression Emission
//===----------------------------------------------------------------------===//
+/// EmitLValue - Emit code to compute a designator that specifies the location
+/// of the expression.
+///
+/// This can return one of two things: a simple address or a bitfield
+/// reference. In either case, the LLVM Value* in the LValue structure is
+/// guaranteed to be an LLVM pointer type.
+///
+/// If this returns a bitfield reference, nothing about the pointee type of
+/// the LLVM value is known: For example, it may not be a pointer to an
+/// integer.
+///
+/// If this returns a normal address, and if the lvalue's C type is fixed
+/// size, this method guarantees that the returned pointer type will point to
+/// an LLVM type of the same size of the lvalue's type. If the lvalue has a
+/// variable length type, this is not possible.
+///
LValue CodeGenFunction::EmitLValue(const Expr *E) {
switch (E->getStmtClass()) {
default:
- printf("Unimplemented lvalue expr!\n");
+ fprintf(stderr, "Unimplemented lvalue expr!\n");
E->dump();
return LValue::getAddr(UndefValue::get(
llvm::PointerType::get(llvm::Type::Int32Ty)));
case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E));
case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+
+
+ case Expr::UnaryOperatorClass:
+ return EmitUnaryOpLValue(cast<UnaryOperator>(E));
}
}
+/// EmitLoadOfLValue - Given an expression that represents a value lvalue,
+/// this method emits the address of the lvalue, then loads the result as an
+/// rvalue, returning the rvalue.
+RValue CodeGenFunction::EmitLoadOfLValue(const Expr *E) {
+ LValue LV = EmitLValue(E);
+
+ QualType ExprTy = E->getType().getCanonicalType();
+
+ // FIXME: this is silly and obviously wrong for non-scalars.
+ assert(!LV.isBitfield());
+ return RValue::get(Builder.CreateLoad(LV.getAddress(), "tmp"));
+}
+
+/// EmitStoreThroughLValue - Store the specified rvalue into the specified
+/// lvalue, where both are guaranteed to the have the same type, and that type
+/// is 'Ty'.
+void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
+ QualType Ty) {
+ // FIXME: This is obviously bogus.
+ assert(!Dst.isBitfield() && "FIXME: Don't support store to bitfield yet");
+ assert(Src.isScalar() && "FIXME: Don't support store of aggregate yet");
+
+ // TODO: Handle volatility etc.
+ Value *Addr = Dst.getAddress();
+ const llvm::Type *SrcTy = Src.getVal()->getType();
+ const llvm::Type *AddrTy =
+ cast<llvm::PointerType>(Addr->getType())->getElementType();
+
+ if (AddrTy != SrcTy)
+ Addr = Builder.CreateBitCast(Addr, llvm::PointerType::get(SrcTy),
+ "storetmp");
+ Builder.CreateStore(Src.getVal(), Addr);
+}
+
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const Decl *D = E->getDecl();
@@ -120,27 +204,33 @@
assert(0 && "Unimp declref");
}
+LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
+ // __extension__ doesn't affect lvalue-ness.
+ if (E->getOpcode() == UnaryOperator::Extension)
+ return EmitLValue(E->getSubExpr());
+
+ assert(E->getOpcode() == UnaryOperator::Deref &&
+ "'*' is the only unary operator that produces an lvalue");
+ return LValue::getAddr(EmitExpr(E->getSubExpr()).getVal());
+}
+
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
-ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
+RValue 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));
+ return RValue::get(UndefValue::get(llvm::Type::Int32Ty));
// l-values.
- case Expr::DeclRefExprClass: {
- // FIXME: EnumConstantDecl's are not lvalues.
- LValue LV = EmitLValue(E);
- // FIXME: this is silly.
- assert(!LV.isBitfield());
- return ExprResult::get(Builder.CreateLoad(LV.getAddress(), "tmp"));
- }
+ case Expr::DeclRefExprClass:
+ // FIXME: EnumConstantDecl's are not lvalues. This is wrong for them.
+ return EmitLoadOfLValue(E);
// Leaf expressions.
case Expr::IntegerLiteralClass:
@@ -151,28 +241,41 @@
return EmitExpr(cast<ParenExpr>(E)->getSubExpr());
case Expr::UnaryOperatorClass:
return EmitUnaryOperator(cast<UnaryOperator>(E));
+ case Expr::CastExprClass:
+ return EmitCastExpr(cast<CastExpr>(E));
case Expr::BinaryOperatorClass:
return EmitBinaryOperator(cast<BinaryOperator>(E));
}
}
-ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
- return ExprResult::get(ConstantInt::get(E->getValue()));
+RValue CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
+ return RValue::get(ConstantInt::get(E->getValue()));
}
-//===--------------------------------------------------------------------===//
-// Unary Operator Emission
-//===--------------------------------------------------------------------===//
+RValue CodeGenFunction::EmitCastExpr(const CastExpr *E) {
+ QualType SrcTy;
+ RValue Src = EmitExprWithUsualUnaryConversions(E->getSubExpr(), SrcTy);
+
+ // If the destination is void, just evaluate the source.
+ if (E->getType()->isVoidType())
+ return RValue::getAggregate(0);
+
+ return EmitConversion(Src, SrcTy, E->getType());
+}
+
+//===----------------------------------------------------------------------===//
+// Unary Operator Emission
+//===----------------------------------------------------------------------===//
-ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E,
- QualType &ResTy) {
+RValue CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E,
+ QualType &ResTy) {
ResTy = E->getType().getCanonicalType();
if (isa<FunctionType>(ResTy)) { // C99 6.3.2.1p4
// Functions are promoted to their address.
ResTy = getContext().getPointerType(ResTy);
- return ExprResult::get(EmitLValue(E).getAddress());
+ return RValue::get(EmitLValue(E).getAddress());
} else if (const ArrayType *ary = dyn_cast<ArrayType>(ResTy)) {
// C99 6.3.2.1p3
ResTy = getContext().getPointerType(ary->getElementType());
@@ -186,8 +289,7 @@
->getElementType()) &&
"Doesn't support VLAs yet!");
llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
- V = Builder.CreateGEP(V, Idx0, Idx0, "arraydecay");
- return ExprResult::get(V);
+ return RValue::get(Builder.CreateGEP(V, Idx0, Idx0, "arraydecay"));
} else if (ResTy->isPromotableIntegerType()) { // C99 6.3.1.1p2
// FIXME: this probably isn't right, pending clarification from Steve.
llvm::Value *Val = EmitExpr(E).getVal();
@@ -201,7 +303,7 @@
}
ResTy = getContext().IntTy;
- return ExprResult::get(Val);
+ return RValue::get(Val);
}
// Otherwise, this is a float, double, int, struct, etc.
@@ -209,23 +311,64 @@
}
-ExprResult CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) {
+RValue 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);
+ return RValue::get(UndefValue::get(llvm::Type::Int32Ty));
+ // FIXME: pre/post inc/dec
+ case UnaryOperator::AddrOf: return EmitUnaryAddrOf(E);
+ case UnaryOperator::Deref : return EmitLoadOfLValue(E);
+ case UnaryOperator::Plus : return EmitUnaryPlus(E);
+ case UnaryOperator::Minus : return EmitUnaryMinus(E);
+ case UnaryOperator::Not : return EmitUnaryNot(E);
+ case UnaryOperator::LNot : return EmitUnaryLNot(E);
+ // FIXME: SIZEOF/ALIGNOF(expr).
+ // FIXME: real/imag
+ case UnaryOperator::Extension: return EmitExpr(E->getSubExpr());
}
}
-/// C99 6.5.3.3
-ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
- QualType ResTy;
- ExprResult Op = EmitExprWithUsualUnaryConversions(E->getSubExpr(), ResTy);
+/// C99 6.5.3.2
+RValue CodeGenFunction::EmitUnaryAddrOf(const UnaryOperator *E) {
+ // The address of the operand is just its lvalue. It cannot be a bitfield.
+ return RValue::get(EmitLValue(E->getSubExpr()).getAddress());
+}
+
+RValue CodeGenFunction::EmitUnaryPlus(const UnaryOperator *E) {
+ // Unary plus just performs promotions on its arithmetic operand.
+ QualType Ty;
+ return EmitExprWithUsualUnaryConversions(E, Ty);
+}
+
+RValue CodeGenFunction::EmitUnaryMinus(const UnaryOperator *E) {
+ // Unary minus performs promotions, then negates its arithmetic operand.
+ QualType Ty;
+ RValue V = EmitExprWithUsualUnaryConversions(E, Ty);
- // Compare to zero.
- Value *BoolVal = EvaluateScalarValueToBool(Op, ResTy);
+ if (V.isScalar())
+ return RValue::get(Builder.CreateNeg(V.getVal(), "neg"));
+
+ assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
+
+RValue CodeGenFunction::EmitUnaryNot(const UnaryOperator *E) {
+ // Unary not performs promotions, then complements its integer operand.
+ QualType Ty;
+ RValue V = EmitExprWithUsualUnaryConversions(E, Ty);
+
+ if (V.isScalar())
+ return RValue::get(Builder.CreateNot(V.getVal(), "neg"));
+
+ assert(0 && "FIXME: This doesn't handle integer complex operands yet (GNU)");
+}
+
+
+/// C99 6.5.3.3
+RValue CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
+ // Compare operand to zero.
+ Value *BoolVal = EvaluateExprAsBool(E->getSubExpr());
// Invert value.
// TODO: Could dynamically modify easy computations here. For example, if
@@ -233,8 +376,7 @@
BoolVal = Builder.CreateNot(BoolVal, "lnot");
// ZExt result to int.
- const llvm::Type *ResLTy = ConvertType(E->getType(), E->getOperatorLoc());
- return ExprResult::get(Builder.CreateZExt(BoolVal, ResLTy, "lnot.ext"));
+ return RValue::get(Builder.CreateZExt(BoolVal, LLVMIntTy, "lnot.ext"));
}
@@ -244,8 +386,8 @@
// FIXME describe.
QualType CodeGenFunction::
-EmitUsualArithmeticConversions(const BinaryOperator *E, ExprResult &LHS,
- ExprResult &RHS) {
+EmitUsualArithmeticConversions(const BinaryOperator *E, RValue &LHS,
+ RValue &RHS) {
QualType LHSType, RHSType;
LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), LHSType);
RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSType);
@@ -290,11 +432,9 @@
// Promote the RHS to an FP type of the LHS, with the sign following the
// RHS.
if (RHSType->isSignedIntegerType())
- RHS = ExprResult::get(Builder.CreateSIToFP(RHSV, LHSV->getType(),
- "promote"));
+ RHS = RValue::get(Builder.CreateSIToFP(RHSV,LHSV->getType(),"promote"));
else
- RHS = ExprResult::get(Builder.CreateUIToFP(RHSV, LHSV->getType(),
- "promote"));
+ RHS = RValue::get(Builder.CreateUIToFP(RHSV,LHSV->getType(),"promote"));
return LHSType;
}
@@ -302,11 +442,9 @@
// Promote the LHS to an FP type of the RHS, with the sign following the
// LHS.
if (LHSType->isSignedIntegerType())
- LHS = ExprResult::get(Builder.CreateSIToFP(LHSV, RHSV->getType(),
- "promote"));
+ LHS = RValue::get(Builder.CreateSIToFP(LHSV,RHSV->getType(),"promote"));
else
- LHS = ExprResult::get(Builder.CreateUIToFP(LHSV, RHSV->getType(),
- "promote"));
+ LHS = RValue::get(Builder.CreateUIToFP(LHSV,RHSV->getType(),"promote"));
return RHSType;
}
@@ -315,11 +453,9 @@
QualType BiggerType = ASTContext::maxFloatingType(LHSType, RHSType);
if (BiggerType == LHSType)
- RHS = ExprResult::get(Builder.CreateFPExt(RHSV, LHSV->getType(),
- "promote"));
+ RHS = RValue::get(Builder.CreateFPExt(RHSV, LHSV->getType(), "promote"));
else
- LHS = ExprResult::get(Builder.CreateFPExt(LHSV, RHSV->getType(),
- "promote"));
+ LHS = RValue::get(Builder.CreateFPExt(LHSV, RHSV->getType(), "promote"));
return BiggerType;
}
@@ -331,40 +467,255 @@
if (LHSType == ResTy) {
if (RHSType->isSignedIntegerType())
- RHS = ExprResult::get(Builder.CreateSExt(RHSV, LHSV->getType(),
- "promote"));
+ RHS = RValue::get(Builder.CreateSExt(RHSV, LHSV->getType(), "promote"));
else
- RHS = ExprResult::get(Builder.CreateZExt(RHSV, LHSV->getType(),
- "promote"));
+ RHS = RValue::get(Builder.CreateZExt(RHSV, LHSV->getType(), "promote"));
} else {
assert(RHSType == ResTy && "Unknown conversion");
if (LHSType->isSignedIntegerType())
- LHS = ExprResult::get(Builder.CreateSExt(LHSV, RHSV->getType(),
- "promote"));
+ LHS = RValue::get(Builder.CreateSExt(LHSV, RHSV->getType(), "promote"));
else
- LHS = ExprResult::get(Builder.CreateZExt(LHSV, RHSV->getType(),
- "promote"));
+ LHS = RValue::get(Builder.CreateZExt(LHSV, RHSV->getType(), "promote"));
}
return ResTy;
}
-ExprResult CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) {
+RValue CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
- printf("Unimplemented expr!\n");
+ fprintf(stderr, "Unimplemented expr!\n");
E->dump();
- return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
+ return RValue::get(UndefValue::get(llvm::Type::Int32Ty));
+ case BinaryOperator::Mul: return EmitBinaryMul(E);
+ case BinaryOperator::Div: return EmitBinaryDiv(E);
+ case BinaryOperator::Rem: return EmitBinaryRem(E);
case BinaryOperator::Add: return EmitBinaryAdd(E);
+ case BinaryOperator::Sub: return EmitBinarySub(E);
+ case BinaryOperator::Shl: return EmitBinaryShl(E);
+ case BinaryOperator::Shr: return EmitBinaryShr(E);
+
+ // FIXME: relational
+
+ case BinaryOperator::And: return EmitBinaryAnd(E);
+ case BinaryOperator::Xor: return EmitBinaryXor(E);
+ case BinaryOperator::Or : return EmitBinaryOr(E);
+ case BinaryOperator::LAnd: return EmitBinaryLAnd(E);
+ case BinaryOperator::LOr: return EmitBinaryLOr(E);
+
+ case BinaryOperator::Assign: return EmitBinaryAssign(E);
+ // FIXME: Assignment.
+ case BinaryOperator::Comma: return EmitBinaryComma(E);
}
}
+RValue CodeGenFunction::EmitBinaryMul(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ if (LHS.isScalar())
+ return RValue::get(Builder.CreateMul(LHS.getVal(), RHS.getVal(), "mul"));
+
+ assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
+
+RValue CodeGenFunction::EmitBinaryDiv(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ if (LHS.isScalar()) {
+ Value *RV;
+ if (LHS.getVal()->getType()->isFloatingPoint())
+ RV = Builder.CreateFDiv(LHS.getVal(), RHS.getVal(), "div");
+ else if (E->getType()->isUnsignedIntegerType())
+ RV = Builder.CreateUDiv(LHS.getVal(), RHS.getVal(), "div");
+ else
+ RV = Builder.CreateSDiv(LHS.getVal(), RHS.getVal(), "div");
+ return RValue::get(RV);
+ }
+ assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
-ExprResult CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) {
- ExprResult LHS, RHS;
+RValue CodeGenFunction::EmitBinaryRem(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ if (LHS.isScalar()) {
+ Value *RV;
+ // Rem in C can't be a floating point type: C99 6.5.5p2.
+ if (E->getType()->isUnsignedIntegerType())
+ RV = Builder.CreateURem(LHS.getVal(), RHS.getVal(), "rem");
+ else
+ RV = Builder.CreateSRem(LHS.getVal(), RHS.getVal(), "rem");
+ return RValue::get(RV);
+ }
+ assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
+
+RValue CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) {
+ RValue LHS, RHS;
EmitUsualArithmeticConversions(E, LHS, RHS);
- // FIXME: This doesn't handle complex addition yet.
- return ExprResult::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "tmp"));
-}
\ No newline at end of file
+ // FIXME: This doesn't handle ptr+int etc yet.
+
+ if (LHS.isScalar())
+ return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add"));
+
+ assert(0 && "FIXME: This doesn't handle complex operands yet");
+
+}
+
+RValue CodeGenFunction::EmitBinarySub(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ // FIXME: This doesn't handle ptr-int or ptr-ptr, etc yet.
+
+ if (LHS.isScalar())
+ return RValue::get(Builder.CreateSub(LHS.getVal(), RHS.getVal(), "sub"));
+
+ assert(0 && "FIXME: This doesn't handle complex operands yet");
+
+}
+
+RValue CodeGenFunction::EmitBinaryShl(const BinaryOperator *E) {
+ // For shifts, integer promotions are performed, but the usual arithmetic
+ // conversions are not. The LHS and RHS need not have the same type.
+
+ QualType ResTy;
+ Value *LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), ResTy).getVal();
+ Value *RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), ResTy).getVal();
+
+ // LLVM requires the LHS and RHS to be the same type, promote or truncate the
+ // RHS to the same size as the LHS.
+ if (LHS->getType() != RHS->getType())
+ RHS = Builder.CreateIntCast(RHS, LHS->getType(), false, "sh_prom");
+
+ return RValue::get(Builder.CreateShl(LHS, RHS, "shl"));
+}
+
+RValue CodeGenFunction::EmitBinaryShr(const BinaryOperator *E) {
+ // For shifts, integer promotions are performed, but the usual arithmetic
+ // conversions are not. The LHS and RHS need not have the same type.
+
+ QualType ResTy;
+ Value *LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), ResTy).getVal();
+ Value *RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), ResTy).getVal();
+
+ // LLVM requires the LHS and RHS to be the same type, promote or truncate the
+ // RHS to the same size as the LHS.
+ if (LHS->getType() != RHS->getType())
+ RHS = Builder.CreateIntCast(RHS, LHS->getType(), false, "sh_prom");
+
+ if (E->getType()->isUnsignedIntegerType())
+ return RValue::get(Builder.CreateLShr(LHS, RHS, "shr"));
+ else
+ return RValue::get(Builder.CreateAShr(LHS, RHS, "shr"));
+}
+
+RValue CodeGenFunction::EmitBinaryAnd(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ if (LHS.isScalar())
+ return RValue::get(Builder.CreateAnd(LHS.getVal(), RHS.getVal(), "and"));
+
+ assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)");
+}
+
+RValue CodeGenFunction::EmitBinaryXor(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ if (LHS.isScalar())
+ return RValue::get(Builder.CreateXor(LHS.getVal(), RHS.getVal(), "xor"));
+
+ assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)");
+}
+
+RValue CodeGenFunction::EmitBinaryOr(const BinaryOperator *E) {
+ RValue LHS, RHS;
+ EmitUsualArithmeticConversions(E, LHS, RHS);
+
+ if (LHS.isScalar())
+ return RValue::get(Builder.CreateOr(LHS.getVal(), RHS.getVal(), "or"));
+
+ assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)");
+}
+
+RValue CodeGenFunction::EmitBinaryLAnd(const BinaryOperator *E) {
+ Value *LHSCond = EvaluateExprAsBool(E->getLHS());
+
+ BasicBlock *ContBlock = new BasicBlock("land_cont");
+ BasicBlock *RHSBlock = new BasicBlock("land_rhs");
+
+ BasicBlock *OrigBlock = Builder.GetInsertBlock();
+ Builder.CreateCondBr(LHSCond, RHSBlock, ContBlock);
+
+ EmitBlock(RHSBlock);
+ Value *RHSCond = EvaluateExprAsBool(E->getRHS());
+
+ // Reaquire the RHS block, as there may be subblocks inserted.
+ RHSBlock = Builder.GetInsertBlock();
+ EmitBlock(ContBlock);
+
+ // Create a PHI node. If we just evaluted the LHS condition, the result is
+ // false. If we evaluated both, the result is the RHS condition.
+ PHINode *PN = Builder.CreatePHI(llvm::Type::Int1Ty, "land");
+ PN->reserveOperandSpace(2);
+ PN->addIncoming(ConstantInt::getFalse(), OrigBlock);
+ PN->addIncoming(RHSCond, RHSBlock);
+
+ // ZExt result to int.
+ return RValue::get(Builder.CreateZExt(PN, LLVMIntTy, "land.ext"));
+}
+
+RValue CodeGenFunction::EmitBinaryLOr(const BinaryOperator *E) {
+ Value *LHSCond = EvaluateExprAsBool(E->getLHS());
+
+ BasicBlock *ContBlock = new BasicBlock("lor_cont");
+ BasicBlock *RHSBlock = new BasicBlock("lor_rhs");
+
+ BasicBlock *OrigBlock = Builder.GetInsertBlock();
+ Builder.CreateCondBr(LHSCond, ContBlock, RHSBlock);
+
+ EmitBlock(RHSBlock);
+ Value *RHSCond = EvaluateExprAsBool(E->getRHS());
+
+ // Reaquire the RHS block, as there may be subblocks inserted.
+ RHSBlock = Builder.GetInsertBlock();
+ EmitBlock(ContBlock);
+
+ // Create a PHI node. If we just evaluted the LHS condition, the result is
+ // true. If we evaluated both, the result is the RHS condition.
+ PHINode *PN = Builder.CreatePHI(llvm::Type::Int1Ty, "lor");
+ PN->reserveOperandSpace(2);
+ PN->addIncoming(ConstantInt::getTrue(), OrigBlock);
+ PN->addIncoming(RHSCond, RHSBlock);
+
+ // ZExt result to int.
+ return RValue::get(Builder.CreateZExt(PN, LLVMIntTy, "lor.ext"));
+}
+
+RValue CodeGenFunction::EmitBinaryAssign(const BinaryOperator *E) {
+ LValue LHS = EmitLValue(E->getLHS());
+
+ QualType RHSTy;
+ RValue RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSTy);
+
+ // Convert the RHS to the type of the LHS.
+ RHS = EmitConversion(RHS, RHSTy, E->getType());
+
+ // Store the value into the LHS.
+ EmitStoreThroughLValue(RHS, LHS, E->getType());
+
+ // Return the converted RHS.
+ return RHS;
+}
+
+
+RValue CodeGenFunction::EmitBinaryComma(const BinaryOperator *E) {
+ EmitExpr(E->getLHS());
+ return EmitExpr(E->getRHS());
+}
Modified: cfe/cfe/trunk/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CGStmt.cpp?rev=39593&r1=39592&r2=39593&view=diff
==============================================================================
--- cfe/cfe/trunk/CodeGen/CGStmt.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGStmt.cpp Wed Jul 11 11:46:02 2007
@@ -45,6 +45,8 @@
case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break;
+ case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break;
+ case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break;
case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
@@ -94,13 +96,9 @@
}
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
- // Emit the if condition.
- QualType CondTy;
- ExprResult CondVal = EmitExprWithUsualUnaryConversions(S.getCond(), CondTy);
-
// 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 = EvaluateScalarValueToBool(CondVal, CondTy);
+ llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
BasicBlock *ContBlock = new BasicBlock("ifend");
BasicBlock *ThenBlock = new BasicBlock("ifthen");
@@ -139,14 +137,10 @@
// Evaluate the conditional in the while header. C99 6.8.5.1: The evaluation
// of the controlling expression takes place before each execution of the loop
// body.
- QualType CondTy;
- ExprResult CondVal = EmitExprWithUsualUnaryConversions(S.getCond(), CondTy);
-
- // C99 6.8.5p2: The first substatement is executed if the expression compares
- // unequal to 0. The condition must be a scalar type.
- llvm::Value *BoolCondVal = EvaluateScalarValueToBool(CondVal, CondTy);
+ llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- // TODO: while(1) is common, avoid extra exit blocks, etc.
+ // TODO: while(1) is common, avoid extra exit blocks, etc. Be sure
+ // to correctly handle break/continue though.
// Create an exit block for when the condition fails, create a block for the
// body of the loop.
@@ -167,12 +161,88 @@
EmitBlock(ExitBlock);
}
+void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
+ // FIXME: Handle continue/break.
+ // TODO: "do {} while (0)" is common in macros, avoid extra blocks. Be sure
+ // to correctly handle break/continue though.
+
+ // Emit the body for the loop, insert it, which will create an uncond br to
+ // it.
+ BasicBlock *LoopBody = new BasicBlock("dobody");
+ BasicBlock *AfterDo = new BasicBlock("afterdo");
+ EmitBlock(LoopBody);
+
+ // Emit the body of the loop into the block.
+ EmitStmt(S.getBody());
+
+ // C99 6.8.5.2: "The evaluation of the controlling expression takes place
+ // after each execution of the loop body."
+
+ // Evaluate the conditional in the while header.
+ // C99 6.8.5p2/p4: The first substatement is executed if the expression
+ // compares unequal to 0. The condition must be a scalar type.
+ llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+ // As long as the condition is true, iterate the loop.
+ Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo);
+
+ // Emit the exit block.
+ EmitBlock(AfterDo);
+}
+
+void CodeGenFunction::EmitForStmt(const ForStmt &S) {
+ // FIXME: Handle continue/break.
+ // FIXME: What do we do if the increment (f.e.) contains a stmt expression,
+ // which contains a continue/break?
+
+ // Evaluate the first part before the loop.
+ if (S.getInit())
+ EmitStmt(S.getInit());
+
+ // Start the loop with a block that tests the condition.
+ BasicBlock *CondBlock = new BasicBlock("forcond");
+ BasicBlock *AfterFor = 0;
+ EmitBlock(CondBlock);
+
+ // Evaluate the condition if present. If not, treat it as a non-zero-constant
+ // according to 6.8.5.3p2, aka, true.
+ if (S.getCond()) {
+ // C99 6.8.5p2/p4: The first substatement is executed if the expression
+ // compares unequal to 0. The condition must be a scalar type.
+ llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+ // As long as the condition is true, iterate the loop.
+ BasicBlock *ForBody = new BasicBlock("forbody");
+ AfterFor = new BasicBlock("afterfor");
+ Builder.CreateCondBr(BoolCondVal, ForBody, AfterFor);
+ EmitBlock(ForBody);
+ } else {
+ // Treat it as a non-zero constant. Don't even create a new block for the
+ // body, just fall into it.
+ }
+
+ // If the condition is true, execute the body of the for stmt.
+ EmitStmt(S.getBody());
+
+ // If there is an increment, emit it next.
+ if (S.getInc())
+ EmitExpr(S.getInc());
+
+ // Finally, branch back up to the condition for the next iteration.
+ Builder.CreateBr(CondBlock);
+
+ // Emit the fall-through block if there is any.
+ if (AfterFor)
+ EmitBlock(AfterFor);
+ else
+ EmitBlock(new BasicBlock());
+}
/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
- ExprResult RetVal;
+ RValue RetVal;
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
@@ -196,8 +266,8 @@
assert(0 && "FIXME: aggregate return unimp");
}
- // Emit a block after the branch so that dead code after a goto has some place
- // to go.
- Builder.SetInsertPoint(new BasicBlock("", CurFn));
+ // Emit a block after the branch so that dead code after a return has some
+ // place to go.
+ EmitBlock(new BasicBlock());
}
Modified: cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp?rev=39593&r1=39592&r2=39593&view=diff
==============================================================================
--- cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp Wed Jul 11 11:46:02 2007
@@ -58,7 +58,9 @@
return IntegerType::get(Target.getCharWidth(Loc));
case BuiltinType::Bool:
- return IntegerType::get(Target.getBoolWidth(Loc));
+ // FIXME: This is very strange. We want scalars to be i1, but in memory
+ // they can be i1 or i32. Should the codegen handle this issue?
+ return llvm::Type::Int1Ty;
case BuiltinType::Short:
case BuiltinType::UShort:
@@ -101,7 +103,7 @@
A.getIndexTypeQualifier() == 0 &&
"FIXME: We only handle trivial array types so far!");
// FIXME: are there any promotions etc here?
- ExprResult Size = EmitExpr(A.getSize());
+ RValue Size = EmitExpr(A.getSize());
assert(Size.isScalar() && isa<llvm::ConstantInt>(Size.getVal()) &&
"FIXME: Only handle fixed-size arrays so far");
const llvm::Type *EltTy = ConvertType(A.getElementType(), Loc);
Modified: cfe/cfe/trunk/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CodeGenFunction.h?rev=39593&r1=39592&r2=39593&view=diff
==============================================================================
--- cfe/cfe/trunk/CodeGen/CodeGenFunction.h (original)
+++ cfe/cfe/trunk/CodeGen/CodeGenFunction.h Wed Jul 11 11:46:02 2007
@@ -33,12 +33,15 @@
class GotoStmt;
class IfStmt;
class WhileStmt;
+ class DoStmt;
+ class ForStmt;
class ReturnStmt;
class DeclStmt;
class Expr;
class DeclRefExpr;
class IntegerLiteral;
+ class CastExpr;
class UnaryOperator;
class BinaryOperator;
@@ -48,11 +51,11 @@
class CodeGenModule;
-/// ExprResult - This trivial value class is used to represent the result of an
+/// RValue - This trivial value class is used to represent the result of an
/// expression that is evaluated. It can be one of two things: either a simple
/// LLVM SSA value, or the address of an aggregate value in memory. These two
/// possibilities are discriminated by isAggregate/isScalar.
-class ExprResult {
+class RValue {
Value *V;
// TODO: Encode this into the low bit of pointer for more efficient
// return-by-value.
@@ -74,14 +77,14 @@
return V;
}
- static ExprResult get(Value *V) {
- ExprResult ER;
+ static RValue get(Value *V) {
+ RValue ER;
ER.V = V;
ER.IsAggregate = false;
return ER;
}
- static ExprResult getAggregate(Value *V) {
- ExprResult ER;
+ static RValue getAggregate(Value *V) {
+ RValue ER;
ER.V = V;
ER.IsAggregate = true;
return ER;
@@ -94,6 +97,7 @@
/// bitrange.
class LValue {
// FIXME: Volatility. Restrict?
+ // alignment?
llvm::Value *V;
public:
bool isBitfield() const { return false; }
@@ -146,10 +150,22 @@
void EmitBlock(BasicBlock *BB);
+
+ /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
+ /// expression and compare the result against zero, returning an Int1Ty value.
+ Value *EvaluateExprAsBool(const Expr *E);
+
+ //===--------------------------------------------------------------------===//
+ // Conversions
+ //===--------------------------------------------------------------------===//
- /// EvaluateScalarValueToBool - Evaluate the specified expression value to a
+ /// EmitConversion - Convert the value specied by Val, whose type is ValTy, to
+ /// the type specified by DstTy, following the rules of C99 6.3.
+ RValue EmitConversion(RValue Val, QualType ValTy, QualType DstTy);
+
+ /// ConvertScalarValueToBool - Convert the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val == 0".
- Value *EvaluateScalarValueToBool(ExprResult Val, QualType Ty);
+ Value *ConvertScalarValueToBool(RValue Val, QualType Ty);
//===--------------------------------------------------------------------===//
// Local Declaration Emission
@@ -170,33 +186,91 @@
void EmitGotoStmt(const GotoStmt &S);
void EmitIfStmt(const IfStmt &S);
void EmitWhileStmt(const WhileStmt &S);
+ void EmitDoStmt(const DoStmt &S);
+ void EmitForStmt(const ForStmt &S);
void EmitReturnStmt(const ReturnStmt &S);
//===--------------------------------------------------------------------===//
// LValue Expression Emission
//===--------------------------------------------------------------------===//
-
+
+ /// EmitLValue - Emit code to compute a designator that specifies the location
+ /// of the expression.
+ ///
+ /// This can return one of two things: a simple address or a bitfield
+ /// reference. In either case, the LLVM Value* in the LValue structure is
+ /// guaranteed to be an LLVM pointer type.
+ ///
+ /// If this returns a bitfield reference, nothing about the pointee type of
+ /// the LLVM value is known: For example, it may not be a pointer to an
+ /// integer.
+ ///
+ /// If this returns a normal address, and if the lvalue's C type is fixed
+ /// size, this method guarantees that the returned pointer type will point to
+ /// an LLVM type of the same size of the lvalue's type. If the lvalue has a
+ /// variable length type, this is not possible.
+ ///
LValue EmitLValue(const Expr *E);
+
+ /// EmitLoadOfLValue - Given an expression that represents a value lvalue,
+ /// this method emits the address of the lvalue, then loads the result as an
+ /// rvalue, returning the rvalue.
+ RValue EmitLoadOfLValue(const Expr *E);
+
+ /// EmitStoreThroughLValue - Store the specified rvalue into the specified
+ /// lvalue, where both are guaranteed to the have the same type, and that type
+ /// is 'Ty'.
+ void EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty);
+
LValue EmitDeclRefLValue(const DeclRefExpr *E);
+ LValue EmitUnaryOpLValue(const UnaryOperator *E);
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
- ExprResult EmitExpr(const Expr *E);
- ExprResult EmitIntegerLiteral(const IntegerLiteral *E);
-
- ExprResult EmitExprWithUsualUnaryConversions(const Expr *E, QualType &ResTy);
+ RValue EmitExprWithUsualUnaryConversions(const Expr *E, QualType &ResTy);
QualType EmitUsualArithmeticConversions(const BinaryOperator *E,
- ExprResult &LHS, ExprResult &RHS);
+ RValue &LHS, RValue &RHS);
+
+ RValue EmitExpr(const Expr *E);
+ RValue EmitIntegerLiteral(const IntegerLiteral *E);
+ RValue EmitCastExpr(const CastExpr *E);
+
// Unary Operators.
- ExprResult EmitUnaryOperator(const UnaryOperator *E);
- ExprResult EmitUnaryLNot(const UnaryOperator *E);
+ RValue EmitUnaryOperator(const UnaryOperator *E);
+ // FIXME: pre/post inc/dec
+ RValue EmitUnaryAddrOf (const UnaryOperator *E);
+ RValue EmitUnaryPlus (const UnaryOperator *E);
+ RValue EmitUnaryMinus (const UnaryOperator *E);
+ RValue EmitUnaryNot (const UnaryOperator *E);
+ RValue EmitUnaryLNot (const UnaryOperator *E);
+ // FIXME: SIZEOF/ALIGNOF(expr).
+ // FIXME: real/imag
// Binary Operators.
- ExprResult EmitBinaryOperator(const BinaryOperator *E);
- ExprResult EmitBinaryAdd(const BinaryOperator *E);
+ RValue EmitBinaryOperator(const BinaryOperator *E);
+ RValue EmitBinaryMul(const BinaryOperator *E);
+ RValue EmitBinaryDiv(const BinaryOperator *E);
+ RValue EmitBinaryRem(const BinaryOperator *E);
+ RValue EmitBinaryAdd(const BinaryOperator *E);
+ RValue EmitBinarySub(const BinaryOperator *E);
+ RValue EmitBinaryShl(const BinaryOperator *E);
+ RValue EmitBinaryShr(const BinaryOperator *E);
+
+ // FIXME: relational
+
+ RValue EmitBinaryAnd(const BinaryOperator *E);
+ RValue EmitBinaryXor(const BinaryOperator *E);
+ RValue EmitBinaryOr (const BinaryOperator *E);
+ RValue EmitBinaryLAnd(const BinaryOperator *E);
+ RValue EmitBinaryLOr(const BinaryOperator *E);
+
+ RValue EmitBinaryAssign(const BinaryOperator *E);
+ // FIXME: Assignment.
+
+ RValue EmitBinaryComma(const BinaryOperator *E);
};
} // end namespace CodeGen
} // end namespace clang
More information about the cfe-commits
mailing list