| Index: lib/Transforms/NaCl/CanonicalizeMemIntrinsics.cpp
|
| diff --git a/lib/Transforms/NaCl/CanonicalizeMemIntrinsics.cpp b/lib/Transforms/NaCl/CanonicalizeMemIntrinsics.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1acde98d322a3f50d44c35ecd75492a4498a0e1b
|
| --- /dev/null
|
| +++ b/lib/Transforms/NaCl/CanonicalizeMemIntrinsics.cpp
|
| @@ -0,0 +1,100 @@
|
| +//===- CanonicalizeMemIntrinsics.cpp - Make memcpy's "len" arg consistent--===//
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// This pass canonicalizes uses of the llvm.memset, llvm.memcpy and
|
| +// llvm.memmove intrinsics so that the variants with 64-bit "len"
|
| +// arguments aren't used, and the 32-bit variants are used instead.
|
| +//
|
| +// This means the PNaCl translator won't need to handle two versions
|
| +// of each of these intrinsics, and it won't need to do any implicit
|
| +// truncations from 64-bit to 32-bit.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#include "llvm/IR/Function.h"
|
| +#include "llvm/IR/IRBuilder.h"
|
| +#include "llvm/IR/Instructions.h"
|
| +#include "llvm/IR/Intrinsics.h"
|
| +#include "llvm/IR/Module.h"
|
| +#include "llvm/Pass.h"
|
| +#include "llvm/Transforms/NaCl.h"
|
| +
|
| +using namespace llvm;
|
| +
|
| +namespace {
|
| + // This is a ModulePass because that makes it easier to find all
|
| + // uses of intrinsics efficiently.
|
| + class CanonicalizeMemIntrinsics : public ModulePass {
|
| + public:
|
| + static char ID; // Pass identification, replacement for typeid
|
| + CanonicalizeMemIntrinsics() : ModulePass(ID) {
|
| + initializeCanonicalizeMemIntrinsicsPass(*PassRegistry::getPassRegistry());
|
| + }
|
| +
|
| + virtual bool runOnModule(Module &M);
|
| + };
|
| +}
|
| +
|
| +char CanonicalizeMemIntrinsics::ID = 0;
|
| +INITIALIZE_PASS(CanonicalizeMemIntrinsics, "canonicalize-mem-intrinsics",
|
| + "Make memcpy() et al's \"len\" argument consistent",
|
| + false, false)
|
| +
|
| +static bool expandIntrinsic(Module *M, Intrinsic::ID ID) {
|
| + SmallVector<Type *, 3> Types;
|
| + Types.push_back(Type::getInt8PtrTy(M->getContext()));
|
| + if (ID != Intrinsic::memset)
|
| + Types.push_back(Type::getInt8PtrTy(M->getContext()));
|
| + unsigned LengthTypePos = Types.size();
|
| + Types.push_back(Type::getInt64Ty(M->getContext()));
|
| +
|
| + std::string OldName = Intrinsic::getName(ID, Types);
|
| + Function *OldIntrinsic = M->getFunction(OldName);
|
| + if (!OldIntrinsic)
|
| + return false;
|
| +
|
| + Types[LengthTypePos] = Type::getInt32Ty(M->getContext());
|
| + Function *NewIntrinsic = Intrinsic::getDeclaration(M, ID, Types);
|
| +
|
| + SmallVector<CallInst *, 64> Calls;
|
| + for (User *U : OldIntrinsic->users()) {
|
| + if (CallInst *Call = dyn_cast<CallInst>(U))
|
| + Calls.push_back(Call);
|
| + else
|
| + report_fatal_error("CanonicalizeMemIntrinsics: Taking the address of an "
|
| + "intrinsic is not allowed: " +
|
| + OldName);
|
| + }
|
| +
|
| + for (CallInst *Call : Calls) {
|
| + // This temporarily leaves Call non-well-typed.
|
| + Call->setCalledFunction(NewIntrinsic);
|
| + // Truncate the "len" argument. No overflow check.
|
| + IRBuilder<> Builder(Call);
|
| + Value *Length = Builder.CreateTrunc(Call->getArgOperand(2),
|
| + Type::getInt32Ty(M->getContext()),
|
| + "mem_len_truncate");
|
| + Call->setArgOperand(2, Length);
|
| + }
|
| +
|
| + OldIntrinsic->eraseFromParent();
|
| + return true;
|
| +}
|
| +
|
| +bool CanonicalizeMemIntrinsics::runOnModule(Module &M) {
|
| + bool Changed = false;
|
| + Changed |= expandIntrinsic(&M, Intrinsic::memset);
|
| + Changed |= expandIntrinsic(&M, Intrinsic::memcpy);
|
| + Changed |= expandIntrinsic(&M, Intrinsic::memmove);
|
| + return Changed;
|
| +}
|
| +
|
| +ModulePass *llvm::createCanonicalizeMemIntrinsicsPass() {
|
| + return new CanonicalizeMemIntrinsics();
|
| +}
|
|
|