Attached is a patch for CodeGen support for AddrOf in constant
initializers. Also attached are tests.

The patch is extremely unintrusive, so it should be easy to review.

Note that this helper should allow some simplifications to the
ImplicitCastExpr and StringLiteral handling in GenerateConstantExpr(),
which is currently a bit of a mess.

Codegen of the address of a string (e.g. &"asdf") will crash due to
inconsistent types without my patch to fix the type of strings;
however, it's a rare construct, and isConstantExpr() currently doesn't
let through such expressions anyway.

There are a few unimplemented cases; the ones I know of are __func__
and the address of a static local.  I left __func__ for later.

The case of the address of a static local is a bit tricky; it's not
possible to resolve correctly with the information available in
GenerateConstantExpr(), as far as I can tell.  It's probably worth
discussing how to fix it.

-Eli
Index: CodeGen/CodeGenModule.cpp
===================================================================
--- CodeGen/CodeGenModule.cpp   (revision 46353)
+++ CodeGen/CodeGenModule.cpp   (working copy)
@@ -356,6 +387,97 @@
   return llvm::ConstantArray::get(AType, Elts);    
 }
 
+/// GenerateStaticAddress - Recursively builds the address of the
+/// given expression.
+static llvm::Constant *GenerateStaticAddress(const Expr *Expression, 
+                                             CodeGenModule &CGM) {
+  CodeGenTypes& Types = CGM.getTypes();
+  switch (Expression->getStmtClass()) {
+  default: assert(0 && "We shouldn't get here");
+  case Expr::ParenExprClass:
+    // Elide parenthesis
+    return GenerateStaticAddress(cast<ParenExpr>(Expression)->getSubExpr(), 
CGM);
+  case Expr::CompoundLiteralExprClass: {
+    // Note that due to the nature of compound literals, this is guaranteed
+    // to be the only use of the variable, so we just generate it here.
+    const CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(Expression);
+    llvm::Constant* C = CGM.EmitGlobalInit(CLE->getInitializer());
+    C = new llvm::GlobalVariable(C->getType(), 
Expression->getType().isConstQualified(), 
+                                 llvm::GlobalValue::InternalLinkage,
+                                 C, ".compoundliteral", &CGM.getModule());
+    return C;
+  }
+  case Expr::DeclRefExprClass: {
+    const ValueDecl *Decl = cast<DeclRefExpr>(Expression)->getDecl();
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
+      return CGM.GetAddrOfFunctionDecl(FD, false);
+    if (const FileVarDecl* FVD = dyn_cast<FileVarDecl>(Decl))
+      return CGM.GetAddrOfGlobalVar(FVD, false);
+    // We can end up here with static block-scope variables (and others?)
+    // FIXME: How do we implement block-scope variables?!
+    break; // UNIMPLEMENTED
+  }
+  case Expr::MemberExprClass: {
+    const MemberExpr* MemExpr = cast<MemberExpr>(Expression);
+    unsigned fieldNumber = Types.getLLVMFieldNo(MemExpr->getMemberDecl());
+    llvm::Constant *Base = GenerateStaticAddress(MemExpr->getBase(), CGM);
+    llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+    llvm::Constant *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty,
+                                                 fieldNumber);
+    llvm::Value *Ops[] = {Zero, Idx};
+    return llvm::ConstantExpr::getGetElementPtr(Base, Ops, 2);
+  }
+  case Expr::ArraySubscriptExprClass: {
+    const ArraySubscriptExpr* ASExpr = cast<ArraySubscriptExpr>(Expression);
+    llvm::Constant *Base = GenerateConstantExpr(ASExpr->getBase(), CGM);
+    llvm::Constant *Index = GenerateConstantExpr(ASExpr->getIdx(), CGM);
+    assert(!ASExpr->getBase()->getType()->isVectorType() &&
+           "Taking the address of a vector component is illegal!");
+    return llvm::ConstantExpr::getGetElementPtr(Base, &Index, 1);
+  }
+  case Expr::PreDefinedExprClass: {
+    break; // UNIMPLEMENTED
+  }
+  case Expr::StringLiteralClass: {
+    const StringLiteral *String = cast<StringLiteral>(Expression);
+    assert(!String->isWide() && "Cannot codegen wide strings yet");
+    const char *StrData = String->getStrData();
+    unsigned Len = String->getByteLength();
+
+    return CGM.GetAddrOfConstantString(std::string(StrData, StrData + Len));
+  }
+  case Expr::UnaryOperatorClass: {
+    const UnaryOperator *Exp = cast<UnaryOperator>(Expression);
+    switch (Exp->getOpcode()) {
+    default: assert(0 && "We shouldn't get here");
+    case UnaryOperator::Extension:
+      // Extension is just a wrapper for expressions
+      return GenerateStaticAddress(Exp->getSubExpr(), CGM);
+    case UnaryOperator::Real:
+    case UnaryOperator::Imag: {
+      // The address of __real or __imag is just a GEP off the address
+      // of the internal expression
+      llvm::Constant* C = GenerateStaticAddress(Exp->getSubExpr(), CGM);
+      llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+      llvm::Constant *Idx  = llvm::ConstantInt::get(llvm::Type::Int32Ty,
+                                         Exp->getOpcode() == 
UnaryOperator::Imag);
+      llvm::Value *Ops[] = {Zero, Idx};
+      return llvm::ConstantExpr::getGetElementPtr(C, Ops, 2);
+    }
+    case UnaryOperator::Deref:
+      // The address of a deref is just the value of the expression
+      return GenerateConstantExpr(Exp->getSubExpr(), CGM);
+    }
+    break;
+  }
+  }
+  CGM.WarnUnsupported(Expression, "initializer");
+  return llvm::UndefValue::get(
+           llvm::PointerType::getUnqual(
+             Types.ConvertType(Expression->getType())));
+}
+
+
 /// GenerateConstantExpr - Recursively builds a constant initialiser for the
 /// given expression.
 static llvm::Constant *GenerateConstantExpr(const Expr *Expression, 
@@ -446,6 +565,9 @@
                                 CGM);
   case Stmt::UnaryOperatorClass: {
     const UnaryOperator *Op = cast<UnaryOperator>(Expression);
+    if (Op->getOpcode() == UnaryOperator::AddrOf) {
+      return GenerateStaticAddress(Op->getSubExpr(), CGM);
+    }
     llvm::Constant *SubExpr = GenerateConstantExpr(Op->getSubExpr(), CGM);
     // FIXME: These aren't right for complex.
     switch (Op->getOpcode()) {
int x1;
struct tt {int a; int b;} x2;
int x3[5];
__complex int x4;
int* b = &x1;
int* c = &(x1);
struct tt* d = &(struct tt){1, 2};
struct tt* d2 = &(struct tt){1, 2};
int* e = &x2.b;
int* f = &x3[2];
//Test broken; sema thinks this isn't constant
//char (*g)[4] = &"abc";
//Test broken; sema doesn't allow address of __extension__
//int* h = &(__extension__ x1);
//Test broken; sema thinks this isn't constant
//int* i = &__imag x4;
//Test broken: sema thinks this isn't constant
//int* j = &*&x1;
int x5(void) {
static int s;
// Unimplemented: currently fail
//static int *t = &s;
//static char (*u)[2] = &__func__;
}
// Test broken: sema thinks this isn't constant
//int (*k)(void) = &x5;
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to