implement codegen of a bunch more loop constructs and most expressions

llvm-svn: 39593
This commit is contained in:
Chris Lattner 2007-06-05 20:53:16 +00:00
parent fdc195af7e
commit 8394d795c3
4 changed files with 598 additions and 101 deletions

View File

@ -23,9 +23,39 @@ using namespace CodeGen;
// 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 @@ Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) {
// 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 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
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 @@ ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
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());
}
ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E,
QualType &ResTy) {
//===----------------------------------------------------------------------===//
// Unary Operator Emission
//===----------------------------------------------------------------------===//
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 @@ ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E,
->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 @@ ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E,
}
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::EmitExprWithUsualUnaryConversions(const Expr *E,
}
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 @@ ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
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 @@ ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
// 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 @@ EmitUsualArithmeticConversions(const BinaryOperator *E, ExprResult &LHS,
// 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 @@ EmitUsualArithmeticConversions(const BinaryOperator *E, ExprResult &LHS,
// 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 @@ EmitUsualArithmeticConversions(const BinaryOperator *E, ExprResult &LHS,
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 @@ EmitUsualArithmeticConversions(const BinaryOperator *E, ExprResult &LHS,
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);
}
}
ExprResult CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) {
ExprResult LHS, RHS;
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");
}
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"));
}
// 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());
}

View File

@ -45,6 +45,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
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::EmitGotoStmt(const GotoStmt &S) {
}
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 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
// 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 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
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 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
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());
}

View File

@ -58,7 +58,9 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
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 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
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);

View File

@ -33,12 +33,15 @@ namespace clang {
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 @@ namespace CodeGen {
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 @@ public:
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 @@ public:
/// bitrange.
class LValue {
// FIXME: Volatility. Restrict?
// alignment?
llvm::Value *V;
public:
bool isBitfield() const { return false; }
@ -146,10 +150,22 @@ public:
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);
/// EvaluateScalarValueToBool - Evaluate the specified expression value to a
//===--------------------------------------------------------------------===//
// 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 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 @@ public:
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