forked from OSchip/llvm-project
implement a first hack at codegen'ing the usual unary conversions.
This allows us to compile: int func() { int A[10]; if (!A) { to: define i32 @func() { entry: %A = alloca [10 x i32] ; <[10 x i32]*> [#uses=1] %arraydecay = getelementptr [10 x i32]* %A, i32 0, i32 0 ; <i32*> [#uses=1] %tobool = icmp ne i32* %arraydecay, null ; <i1> [#uses=1] %lnot = xor i1 %tobool, true ; <i1> [#uses=1] br i1 %lnot, label %ifthen, label %ifend -Chris llvm-svn: 39564
This commit is contained in:
parent
226d419e21
commit
6db1fb845a
|
@ -163,6 +163,52 @@ ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
|
|||
// Unary Operator Emission
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
ExprResult 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());
|
||||
} else if (const ArrayType *ary = dyn_cast<ArrayType>(ResTy)) {
|
||||
// C99 6.3.2.1p3
|
||||
ResTy = getContext().getPointerType(ary->getElementType());
|
||||
|
||||
// FIXME: For now we assume that all source arrays map to LLVM arrays. This
|
||||
// will not true when we add support for VLAs.
|
||||
llvm::Value *V = EmitLValue(E).getAddress(); // Bitfields can't be arrays.
|
||||
|
||||
assert(isa<llvm::PointerType>(V->getType()) &&
|
||||
isa<llvm::ArrayType>(cast<llvm::PointerType>(V->getType())
|
||||
->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);
|
||||
} 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();
|
||||
|
||||
// FIXME: this doesn't handle 'char'!.
|
||||
|
||||
// If the input is a signed integer, sign extend to the destination.
|
||||
if (ResTy->isSignedIntegerType()) {
|
||||
Val = Builder.CreateSExt(Val, LLVMIntTy, "promote");
|
||||
} else {
|
||||
// This handles unsigned types, including bool.
|
||||
Val = Builder.CreateZExt(Val, LLVMIntTy, "promote");
|
||||
}
|
||||
ResTy = getContext().IntTy;
|
||||
|
||||
return ExprResult::get(Val);
|
||||
}
|
||||
|
||||
// Otherwise, this is a float, double, int, struct, etc.
|
||||
return EmitExpr(E);
|
||||
}
|
||||
|
||||
|
||||
ExprResult CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) {
|
||||
switch (E->getOpcode()) {
|
||||
default:
|
||||
|
@ -175,12 +221,11 @@ ExprResult CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) {
|
|||
|
||||
/// C99 6.5.3.3
|
||||
ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
|
||||
ExprResult Op = EmitExpr(E->getSubExpr());
|
||||
|
||||
//UsualUnary();
|
||||
QualType ResTy;
|
||||
ExprResult Op = EmitExprWithUsualUnaryConversions(E->getSubExpr(), ResTy);
|
||||
|
||||
// Compare to zero.
|
||||
Value *BoolVal = EvaluateScalarValueToBool(Op, E->getSubExpr()->getType());
|
||||
Value *BoolVal = EvaluateScalarValueToBool(Op, ResTy);
|
||||
|
||||
// Invert value.
|
||||
// TODO: Could dynamically modify easy computations here. For example, if
|
||||
|
@ -188,8 +233,8 @@ ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
|
|||
BoolVal = Builder.CreateNot(BoolVal, "lnot");
|
||||
|
||||
// ZExt result to int.
|
||||
const llvm::Type *ResTy = ConvertType(E->getType(), E->getOperatorLoc());
|
||||
return ExprResult::get(Builder.CreateZExt(BoolVal, ResTy, "lnot.ext"));
|
||||
const llvm::Type *ResLTy = ConvertType(E->getType(), E->getOperatorLoc());
|
||||
return ExprResult::get(Builder.CreateZExt(BoolVal, ResLTy, "lnot.ext"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@ using namespace CodeGen;
|
|||
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
||||
: CGM(cgm), Target(CGM.getContext().Target) {}
|
||||
|
||||
ASTContext &CodeGenFunction::getContext() const {
|
||||
return CGM.getContext();
|
||||
}
|
||||
|
||||
|
||||
llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
|
||||
BasicBlock *&BB = LabelMap[S];
|
||||
|
@ -131,6 +135,8 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
|
|||
|
||||
|
||||
void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy, FD->getLocation());
|
||||
|
||||
const llvm::FunctionType *Ty =
|
||||
cast<llvm::FunctionType>(ConvertType(FD->getType(), FD->getLocation()));
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ class CodeGenFunction {
|
|||
/// we prefer to insert allocas.
|
||||
llvm::Instruction *AllocaInsertPt;
|
||||
|
||||
const llvm::Type *LLVMIntTy;
|
||||
|
||||
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
|
||||
/// decls.
|
||||
DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
|
||||
|
@ -129,6 +131,8 @@ class CodeGenFunction {
|
|||
public:
|
||||
CodeGenFunction(CodeGenModule &cgm);
|
||||
|
||||
ASTContext &getContext() const;
|
||||
|
||||
const llvm::Type *ConvertType(QualType T, SourceLocation Loc);
|
||||
|
||||
void GenerateCode(const FunctionDecl *FD);
|
||||
|
@ -180,7 +184,7 @@ public:
|
|||
ExprResult EmitExpr(const Expr *E);
|
||||
ExprResult EmitIntegerLiteral(const IntegerLiteral *E);
|
||||
|
||||
|
||||
ExprResult EmitExprWithUsualUnaryConversions(const Expr *E, QualType &ResTy);
|
||||
void EmitUsualArithmeticConversions(const BinaryOperator *E,
|
||||
ExprResult &LHS, ExprResult &RHS);
|
||||
|
||||
|
|
Loading…
Reference in New Issue