diff options
author | Mark Seaborn <mseaborn@chromium.org> | 2013-06-03 11:33:57 -0700 |
---|---|---|
committer | Mark Seaborn <mseaborn@chromium.org> | 2013-06-03 11:33:57 -0700 |
commit | eedf1e284837398d8eeaf0972e906236380378dd (patch) | |
tree | 2cf8257943d6270930e2a6bf9eb1f1138e84245e | |
parent | 4358dd390dc7f621a5ce427a2d1fc3577ac70ef5 (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.cpp | 20 | ||||
-rw-r--r-- | test/Transforms/NaCl/replace-ptrs-with-ints.ll | 15 |
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* |