]> granicus.if.org Git - clang/commitdiff
Inspired by seeing "MIPS" go by in the commits, I've gone ahead and
authorJohn McCall <rjmccall@apple.com>
Tue, 2 Mar 2010 03:50:12 +0000 (03:50 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 2 Mar 2010 03:50:12 +0000 (03:50 +0000)
implemented a (codegen) target hook for __builtin_extend_pointer.
I'm also making it return a uint64_t instead of an unsigned word;  this
comports with typical usage (i.e. the one use I know of).

I don't know if any of the existing targets requires this hook to be
set (other than x86 and x86_64, which I know do not).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97547 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Builtins.def
lib/CodeGen/CGBuiltin.cpp
lib/CodeGen/TargetInfo.h

index ac1660a6eafd8857d712eb67e70f4c85beb5b77a..9442ac328700907a2c3ddabc8af65f594acb4b5b 100644 (file)
@@ -317,7 +317,7 @@ BUILTIN(__builtin_frob_return_addr, "v*v*", "n")
 BUILTIN(__builtin_dwarf_cfa, "v*", "n")
 BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
 BUILTIN(__builtin_dwarf_sp_column, "Ui", "n")
-BUILTIN(__builtin_extend_pointer, "zv*", "n") // Really _Unwind_Ptr -> _Unwind_Word
+BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t
 
 // GCC Object size checking builtins
 BUILTIN(__builtin_object_size, "zv*i", "n")
index 1956abf39f362ad83e35d8e849a36e847db4e1f2..0c875f78b1cffaccab3d1541fd7182e55e8b36d0 100644 (file)
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "TargetInfo.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "clang/Basic/TargetInfo.h"
@@ -19,6 +20,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "llvm/Intrinsics.h"
+#include "llvm/Target/TargetData.h"
 using namespace clang;
 using namespace CodeGen;
 using namespace llvm;
@@ -367,19 +369,32 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
   }
   case Builtin::BI__builtin_extend_pointer: {
     // Extends a pointer to the size of an _Unwind_Word, which is
-    // generally a uint64_t.  Generally this gets poked directly into
-    // a register (or a "register" depending on platform) and then
-    // called, so if the pointer is shorter than a word we need to
-    // zext / sext based on the platform's expectations for pointers
-    // in registers.
+    // uint64_t on all platforms.  Generally this gets poked into a
+    // register and eventually used as an address, so if the
+    // addressing registers are wider than pointers and the platform
+    // doesn't implicitly ignore high-order bits when doing
+    // addressing, we need to make sure we zext / sext based on
+    // the platform's expectations.
     //
     // See: http://gcc.gnu.org/ml/gcc-bugs/2002-02/msg00237.html
-    //
-    // FIXME: ptrtoint always zexts; use a target hook if we start
-    // supporting targets where this matters.
+
+    LLVMContext &C = CGM.getLLVMContext();
+
+    // Cast the pointer to intptr_t.
     Value *Ptr = EmitScalarExpr(E->getArg(0));
-    const llvm::Type *Ty = CGM.getTypes().ConvertType(E->getType());
-    return RValue::get(Builder.CreatePtrToInt(Ptr, Ty));
+    const llvm::IntegerType *IntPtrTy = CGM.getTargetData().getIntPtrType(C);
+    Value *Result = Builder.CreatePtrToInt(Ptr, IntPtrTy, "extend.cast");
+
+    // If that's 64 bits, we're done.
+    if (IntPtrTy->getBitWidth() == 64)
+      return RValue::get(Result);
+
+    // Otherwise, ask the codegen data what to do.
+    const llvm::IntegerType *Int64Ty = llvm::IntegerType::get(C, 64);
+    if (CGM.getTargetCodeGenInfo().extendPointerWithSExt())
+      return RValue::get(Builder.CreateSExt(Result, Int64Ty, "extend.sext"));
+    else
+      return RValue::get(Builder.CreateZExt(Result, Int64Ty, "extend.zext"));
   }
 #if 0
   // FIXME: Finish/enable when LLVM backend support stabilizes
index 58b7b79224fd29e44390223ec007aca35bf1f908..b8a374c1348d32f0c56b7b9f00a20062bc1da363 100644 (file)
@@ -44,6 +44,15 @@ namespace clang {
     /// target-specific attributes for the given global.
     virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
                                      CodeGen::CodeGenModule &M) const { }
+
+    /// Controls whether __builtin_extend_pointer should sign-extend
+    /// pointers to uint64_t or zero-extend them (the default).  Has
+    /// no effect for targets:
+    ///   - that have 64-bit pointers, or
+    ///   - that cannot address through registers larger than pointers, or
+    ///   - that implicitly ignore/truncate the top bits when addressing
+    ///     through such registers.
+    virtual bool extendPointerWithSExt() const { return false; }
   };
 }