| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 //===- RewriteAsmDirectives.cpp - Handle Architecture-Independent Assembly-===// |  | 
| 2 // |  | 
| 3 //                     The LLVM Compiler Infrastructure |  | 
| 4 // |  | 
| 5 // This file is distributed under the University of Illinois Open Source |  | 
| 6 // License. See LICENSE.TXT for details. |  | 
| 7 // |  | 
| 8 //===----------------------------------------------------------------------===// |  | 
| 9 // |  | 
| 10 // This pass rewrites any inline assembly directive which is portable |  | 
| 11 // into LLVM bitcode. |  | 
| 12 // |  | 
| 13 //===----------------------------------------------------------------------===// |  | 
| 14 |  | 
| 15 #include "llvm/ADT/Twine.h" |  | 
| 16 #include "llvm/IR/Function.h" |  | 
| 17 #include "llvm/IR/InlineAsm.h" |  | 
| 18 #include "llvm/IR/Instructions.h" |  | 
| 19 #include "llvm/IR/Module.h" |  | 
| 20 #include "llvm/InstVisitor.h" |  | 
| 21 #include "llvm/Pass.h" |  | 
| 22 #include <string> |  | 
| 23 |  | 
| 24 using namespace llvm; |  | 
| 25 |  | 
| 26 namespace { |  | 
| 27 class RewriteAsmDirectives : public FunctionPass { |  | 
| 28 public: |  | 
| 29   static char ID; // Pass identification, replacement for typeid |  | 
| 30   RewriteAsmDirectives() : FunctionPass(ID) { |  | 
| 31     initializeRewriteAsmDirectivesPass(*PassRegistry::getPassRegistry()); |  | 
| 32   } |  | 
| 33 |  | 
| 34   virtual bool runOnFunction(Function &F); |  | 
| 35 }; |  | 
| 36 |  | 
| 37 class AsmDirectivesVisitor : public InstVisitor<AsmDirectivesVisitor> { |  | 
| 38 public: |  | 
| 39   AsmDirectivesVisitor(Function &F) |  | 
| 40       : F(F), C(F.getParent()->getContext()), ModifiedFunction(false) {} |  | 
| 41   ~AsmDirectivesVisitor() {} |  | 
| 42   bool modifiedFunction() const { return ModifiedFunction; } |  | 
| 43 |  | 
| 44   /// Only Call Instructions are ever inline assembly directives. |  | 
| 45   void visitCallInst(CallInst &CI); |  | 
| 46 |  | 
| 47 private: |  | 
| 48   Function &F; |  | 
| 49   LLVMContext &C; |  | 
| 50   bool ModifiedFunction; |  | 
| 51 |  | 
| 52   AsmDirectivesVisitor() LLVM_DELETED_FUNCTION; |  | 
| 53   AsmDirectivesVisitor(const AsmDirectivesVisitor &) LLVM_DELETED_FUNCTION; |  | 
| 54   AsmDirectivesVisitor &operator=(const AsmDirectivesVisitor &) LLVM_DELETED_FUN
     CTION; |  | 
| 55 }; |  | 
| 56 } |  | 
| 57 |  | 
| 58 char RewriteAsmDirectives::ID = 0; |  | 
| 59 INITIALIZE_PASS( |  | 
| 60     RewriteAsmDirectives, "rewrite-asm-directives", |  | 
| 61     "rewrite portable inline assembly directives into non-asm LLVM IR", |  | 
| 62     false, false) |  | 
| 63 |  | 
| 64 bool RewriteAsmDirectives::runOnFunction(Function &F) { |  | 
| 65   AsmDirectivesVisitor AV(F); |  | 
| 66   AV.visit(F); |  | 
| 67   return AV.modifiedFunction(); |  | 
| 68 } |  | 
| 69 |  | 
| 70 void AsmDirectivesVisitor::visitCallInst(CallInst &CI) { |  | 
| 71   if (!CI.isInlineAsm()) |  | 
| 72     return; |  | 
| 73 |  | 
| 74   Instruction *Replacement = NULL; |  | 
| 75 |  | 
| 76   InlineAsm *IA = cast<InlineAsm>(CI.getCalledValue()); |  | 
| 77   std::string AsmStr(IA->getAsmString()); |  | 
| 78   std::string ConstraintStr(IA->getConstraintString()); |  | 
| 79   Type *T = CI.getType(); |  | 
| 80 |  | 
| 81   bool isEmptyAsm = AsmStr.empty(); |  | 
| 82   // Different triples will encode "touch everything" differently, e.g.: |  | 
| 83   //  - le32-unknown-nacl has "~{memory}". |  | 
| 84   //  - x86 "~{memory},~{dirflag},~{fpsr},~{flags}". |  | 
| 85   // The following code therefore only searches for memory: this pass |  | 
| 86   // deals with portable assembly, touching anything else than memory in |  | 
| 87   // an empty assembly statement is meaningless. |  | 
| 88   bool touchesMemory = ConstraintStr.find("~{memory}") != std::string::npos; |  | 
| 89 |  | 
| 90   if (T->isVoidTy() && IA->hasSideEffects() && isEmptyAsm && touchesMemory) { |  | 
| 91     // asm("":::"memory") => fence seq_cst |  | 
| 92     // This transformation is safe and strictly stronger: the former is |  | 
| 93     // purely a compiler fence, whereas the latter is a compiler fence |  | 
| 94     // as well as a hardware fence which orders all loads and stores on |  | 
| 95     // the current thread of execution. |  | 
| 96     Replacement = new FenceInst(C, SequentiallyConsistent, CrossThread, &CI); |  | 
| 97   } |  | 
| 98 |  | 
| 99   if (Replacement) { |  | 
| 100     Replacement->setDebugLoc(CI.getDebugLoc()); |  | 
| 101     CI.replaceAllUsesWith(Replacement); |  | 
| 102     CI.eraseFromParent(); |  | 
| 103     ModifiedFunction = true; |  | 
| 104   } |  | 
| 105 } |  | 
| 106 |  | 
| 107 namespace llvm { |  | 
| 108 FunctionPass *createRewriteAsmDirectivesPass() { |  | 
| 109   return new RewriteAsmDirectives(); |  | 
| 110 } |  | 
| 111 } |  | 
| OLD | NEW | 
|---|