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:
Chris Lattner 2007-06-02 22:49:07 +00:00
parent 226d419e21
commit 6db1fb845a
3 changed files with 62 additions and 7 deletions

View File

@ -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"));
}

View File

@ -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()));

View File

@ -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);