aboutsummaryrefslogtreecommitdiff
path: root/CodeGen/CGExprConstant.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2008-01-26 02:08:50 +0000
committerAnders Carlsson <andersca@mac.com>2008-01-26 02:08:50 +0000
commite3d3b7d44ffb69ad7a756de50dda2f22441f5d0d (patch)
treeff6f946aad17cc2fc979fe612cb64a40495d549c /CodeGen/CGExprConstant.cpp
parent3b1d57b623702865e4158b00cb1d984ba6dd5d50 (diff)
Add CodeGen for AddrOf in constant initializers. Original patch by Eli Friedman.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46388 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'CodeGen/CGExprConstant.cpp')
-rw-r--r--CodeGen/CGExprConstant.cpp89
1 files changed, 88 insertions, 1 deletions
diff --git a/CodeGen/CGExprConstant.cpp b/CodeGen/CGExprConstant.cpp
index 3e91bc2337..4b3b3cb8be 100644
--- a/CodeGen/CGExprConstant.cpp
+++ b/CodeGen/CGExprConstant.cpp
@@ -237,6 +237,9 @@ public:
llvm::Constant *VisitUnaryAlignOf(const UnaryOperator *E) {
return EmitSizeAlignOf(E->getSubExpr()->getType(), E->getType(), false);
}
+ llvm::Constant *VisitUnaryAddrOf(const UnaryOperator *E) {
+ return EmitLValue(E->getSubExpr());
+ }
// Utility methods
const llvm::Type *ConvertType(QualType T) {
@@ -351,7 +354,91 @@ public:
return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));
}
- };
+ llvm::Constant *EmitLValue(const Expr *E) {
+ switch (E->getStmtClass()) {
+ default: {
+ CGM.WarnUnsupported(E, "constant l-value expression");
+ llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
+ return llvm::UndefValue::get(Ty);
+ }
+ case Expr::ParenExprClass:
+ // Elide parenthesis
+ return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+ 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>(E);
+ llvm::Constant* C = CGM.EmitGlobalInit(CLE->getInitializer());
+ C =new llvm::GlobalVariable(C->getType(), E->getType().isConstQualified(),
+ llvm::GlobalValue::InternalLinkage,
+ C, ".compoundliteral", &CGM.getModule());
+ return C;
+ }
+ case Expr::DeclRefExprClass: {
+ const ValueDecl *Decl = cast<DeclRefExpr>(E)->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?!
+ assert(0 && "Unimplemented Decl type");
+ return 0;
+ }
+ case Expr::MemberExprClass: {
+ const MemberExpr* ME = cast<MemberExpr>(E);
+ unsigned FieldNumber = CGM.getTypes().getLLVMFieldNo(ME->getMemberDecl());
+ llvm::Constant *Base = EmitLValue(ME->getBase());
+ 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>(E);
+ llvm::Constant *Base = EmitLValue(ASExpr->getBase());
+ llvm::Constant *Index = EmitLValue(ASExpr->getIdx());
+ assert(!ASExpr->getBase()->getType()->isVectorType() &&
+ "Taking the address of a vector component is illegal!");
+ return llvm::ConstantExpr::getGetElementPtr(Base, &Index, 1);
+ }
+ case Expr::StringLiteralClass: {
+ const StringLiteral *String = cast<StringLiteral>(E);
+ 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>(E);
+ switch (Exp->getOpcode()) {
+ default: assert(0 && "Unsupported unary operator.");
+ case UnaryOperator::Extension:
+ // Extension is just a wrapper for expressions
+ return EmitLValue(Exp->getSubExpr());
+ 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 = EmitLValue(Exp->getSubExpr());
+ 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 Visit(Exp->getSubExpr());
+ }
+ }
+ }
+}
+
+};
+
} // end anonymous namespace.