aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Seaborn <mseaborn@chromium.org>2013-06-03 11:33:57 -0700
committerMark Seaborn <mseaborn@chromium.org>2013-06-03 11:33:57 -0700
commiteedf1e284837398d8eeaf0972e906236380378dd (patch)
tree2cf8257943d6270930e2a6bf9eb1f1138e84245e
parent4358dd390dc7f621a5ce427a2d1fc3577ac70ef5 (diff)
PNaCl: Fix ReplacePtrsWithInts so that ptrtoint always casts to i32
The normal form introduced by ReplacePtrsWithInts (as documented in the comments) is intended to have the property that ptrtoint and inttoptr only convert to/from i32, not other size types. Using IRBuilder's CreateZExtOrTrunc() broke that, though, because it performs some constant folding on global variable references. Fix this by creating CastInsts directly. I found this via the ABI checks I've been writing, which gave this error when building the sandboxed translator: non-i32 ptrtoint: %expanded1 = ptrtoint void ()* @ARMCompilationCallback to i8 LLVM ERROR: PNaCl ABI verification failed BUG=https://code.google.com/p/nativeclient/issues/detail?id=3343 TEST=*.ll tests + tested full PNaCl build with ABI checks applied too Review URL: https://codereview.chromium.org/15955012
-rw-r--r--lib/Transforms/NaCl/ReplacePtrsWithInts.cpp20
-rw-r--r--test/Transforms/NaCl/replace-ptrs-with-ints.ll15
2 files changed, 31 insertions, 4 deletions
diff --git a/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp b/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp
index 9be459d986..03d42e072c 100644
--- a/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp
+++ b/lib/Transforms/NaCl/ReplacePtrsWithInts.cpp
@@ -48,7 +48,6 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
-#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
@@ -373,9 +372,22 @@ static void ConvertInstruction(DataLayout *DL, Type *IntPtrType,
} else if (isa<PtrToIntInst>(Inst) || isa<IntToPtrInst>(Inst)) {
Value *Arg = FC->convert(Inst->getOperand(0));
Type *ResultTy = FC->convertType(Inst->getType());
- IRBuilder<> Builder(Inst);
- Builder.SetCurrentDebugLocation(Inst->getDebugLoc());
- Value *Result = Builder.CreateZExtOrTrunc(Arg, ResultTy, "");
+ unsigned ArgSize = Arg->getType()->getIntegerBitWidth();
+ unsigned ResultSize = ResultTy->getIntegerBitWidth();
+ Value *Result;
+ // We avoid using IRBuilder's CreateZExtOrTrunc() here because it
+ // constant-folds ptrtoint ConstantExprs. This leads to creating
+ // ptrtoints of non-IntPtrType type, which is not what we want,
+ // because we want truncation/extension to be done explicitly by
+ // separate instructions.
+ if (ArgSize == ResultSize) {
+ Result = Arg;
+ } else {
+ Instruction::CastOps CastType =
+ ArgSize > ResultSize ? Instruction::Trunc : Instruction::ZExt;
+ Result = CopyDebug(CastInst::Create(CastType, Arg, ResultTy, "", Inst),
+ Inst);
+ }
if (Result != Arg)
Result->takeName(Inst);
FC->recordConvertedAndErase(Inst, Result);
diff --git a/test/Transforms/NaCl/replace-ptrs-with-ints.ll b/test/Transforms/NaCl/replace-ptrs-with-ints.ll
index d7e85f6da6..5a8f58dbaf 100644
--- a/test/Transforms/NaCl/replace-ptrs-with-ints.ll
+++ b/test/Transforms/NaCl/replace-ptrs-with-ints.ll
@@ -141,6 +141,21 @@ define i32* @ptrtoint_different_size(i32* %ptr) {
; CHECK-NEXT: %c = trunc i64 %b to i32
; CHECK-NEXT: ret i32 %c
+define i8 @ptrtoint_truncates_var(i32* %ptr) {
+ %a = ptrtoint i32* %ptr to i8
+ ret i8 %a
+}
+; CHECK: define i8 @ptrtoint_truncates_var(i32 %ptr) {
+; CHECK-NEXT: %a = trunc i32 %ptr to i8
+
+define i8 @ptrtoint_truncates_global() {
+ %a = ptrtoint i32* @var to i8
+ ret i8 %a
+}
+; CHECK: define i8 @ptrtoint_truncates_global() {
+; CHECK-NEXT: %expanded = ptrtoint i32* @var to i32
+; CHECK-NEXT: %a = trunc i32 %expanded to i8
+
define i32* @pointer_bitcast(i64* %ptr) {
%cast = bitcast i64* %ptr to i32*