implement codegen of a bunch more loop constructs and most expressions
llvm-svn: 39593
This commit is contained in:
parent
fdc195af7e
commit
8394d795c3
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue