Implement __builtin_offsetof.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46515 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CodeGen/CGExprConstant.cpp b/CodeGen/CGExprConstant.cpp
index 3b1c62b..e03db99 100644
--- a/CodeGen/CGExprConstant.cpp
+++ b/CodeGen/CGExprConstant.cpp
@@ -235,6 +235,15 @@
   llvm::Constant *VisitUnaryAddrOf(const UnaryOperator *E) {
     return EmitLValue(E->getSubExpr());
   }
+  llvm::Constant *VisitUnaryOffsetOf(const UnaryOperator *E) {
+    int64_t Val = E->evaluateOffsetOf(CGM.getContext());
+    
+    assert(E->getType()->isIntegerType() && "Result type must be an integer!");
+    
+    uint32_t ResultWidth = static_cast<uint32_t>(
+      CGM.getContext().getTypeSize(E->getType(), SourceLocation()));
+    return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));    
+  }
   
   // Binary operators
   llvm::Constant *VisitBinOr(const BinaryOperator *E) {
diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp
index 652729a..e1771e8 100644
--- a/CodeGen/CGExprScalar.cpp
+++ b/CodeGen/CGExprScalar.cpp
@@ -213,7 +213,8 @@
   Value *VisitUnaryExtension(const UnaryOperator *E) {
     return Visit(E->getSubExpr());
   }
-  
+  Value *VisitUnaryOffsetOf(const UnaryOperator *E);
+    
   // Binary Operators.
   Value *EmitMul(const BinOpInfo &Ops) {
     return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
@@ -628,6 +629,16 @@
   return llvm::Constant::getNullValue(ConvertType(E->getType()));
 }
 
+Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E)
+{
+  int64_t Val = E->evaluateOffsetOf(CGF.getContext());
+  
+  assert(E->getType()->isIntegerType() && "Result type must be an integer!");
+  
+  uint32_t ResultWidth = static_cast<uint32_t>(
+    CGF.getContext().getTypeSize(E->getType(), SourceLocation()));
+  return llvm::ConstantInt::get(llvm::APInt(ResultWidth, Val));
+}
 
 //===----------------------------------------------------------------------===//
 //                           Binary Operators