Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.08 KB | None | 0 0
  1. //Owen Stenson
  2. //LLVM hw2
  3.  
  4. /* Note about how this works
  5.  * This method relies on programs having a particular structure, and so only works
  6.  *  with a small subset of possible programs, i.e. those which only do basic
  7.  *  manipulations on global variables.
  8.  *      Viable llvm IRs must be composed of one or more subblocks of the form
  9.  *          * Mandatory load instruction (variable to register)
  10.  *          * Optional load instruction (variable to register)
  11.  *          * Mandatory operation (binary or unary)
  12.  *          * Mandatory store operation (register to variable)
  13.  *      The sample inputs are in this form and it makes things easier to reason about.
  14.  *      In an effort to not build up an enormous data structure, these subblocks
  15.  *       are identified one at a time and modified in place.
  16.  */
  17.  
  18. #include "llvm/Support/raw_ostream.h"
  19. #include "llvm/IR/IRBuilder.h"
  20. #include "llvm/IR/InstVisitor.h"
  21. #include "llvm/Transforms/Utils/BasicBlockUtils.h"
  22. #include <vector>
  23.  
  24.  
  25. using namespace llvm;
  26.  
  27. namespace {
  28.     class Subblock {
  29.         public:
  30.             Subblock();
  31.             int insert(Instruction &I);
  32.             void clear();
  33.             void print();
  34.             int invert();
  35.             Instruction *load1;
  36.             Instruction *load2;
  37.             Instruction *op;
  38.             Instruction *store;
  39.     };
  40.     Subblock::Subblock() : load1(NULL), load2(NULL), op(NULL), store(NULL) {}
  41.     void Subblock::clear() {
  42.         load1 = NULL;
  43.         load2 = NULL;
  44.         op = NULL;
  45.         store = NULL;
  46.     }
  47.     void Subblock::print() {
  48.         LoadInst *p1 = dyn_cast<LoadInst>(load1);
  49.         StoreInst *s  = dyn_cast<StoreInst>(store);
  50.  
  51.         errs() << "\tLoad 1: ('" << p1->getPointerOperand()->getName() << "'):  `";
  52.         p1->print(errs());
  53.         errs() << "`\n";
  54.  
  55.         if (load2 == NULL) {
  56.             errs() << "\tLoad 2: NULL\n";
  57.         } else {
  58.             LoadInst *p2 = dyn_cast<LoadInst>(load2);
  59.             errs() << "\tLoad 2: ('" << p2->getPointerOperand()->getName() << "'):  `";
  60.             p2->print(errs());
  61.             errs() << "`\n";
  62.         }
  63.  
  64.         errs() << "\tOp:  `";
  65.         op->print(errs());
  66.         errs() << "`\n";
  67.  
  68.         errs() << "\tStore: ('" << s->getPointerOperand()->getName() << "')  `";
  69.         store->print(errs());
  70.         errs() << "`\n";
  71.     }
  72.     int Subblock::insert(Instruction &I) {
  73.         //returns -1 on error
  74.         //returns  0 on success
  75.         //returns +1 on completion (after `store`)
  76.         if (LoadInst *load = dyn_cast<LoadInst>(&I)) {
  77.             if(load1 == NULL) {
  78.                 load1 = load;
  79.             } else if(load2 == NULL) {
  80.                 load2 = load;
  81.             } else {
  82.                 errs() << "Found more than 2 loads in a subblock; you're boned\n";
  83.                 return -1;
  84.             }
  85.             return 0;
  86.         } else if (BinaryOperator *bo = dyn_cast<BinaryOperator>(&I)) {
  87.             if(op == NULL) {
  88.                 op = bo;
  89.                 return 0;
  90.             } else {
  91.                 errs() << "Found more than 1 operation in a subblock; you're boned\n";
  92.                 return -1;
  93.             }  
  94.         } else if (StoreInst *s = dyn_cast<StoreInst>(&I)) {
  95.             if(store == NULL) {
  96.                 store = s;
  97.                 return 1;
  98.             } else {
  99.                 errs() << "Found more than 1 store in a subblock; you're boned\n";
  100.                 return -1;
  101.             }
  102.         } else {
  103.             errs() << "Encountered an unknown instruction:\n";
  104.             I.print(errs());
  105.             errs() << "\n";
  106.             return -1;
  107.         }
  108.     }
  109.     int Subblock::invert() {
  110.         //TODO: don't try to modify in place to avoid memory issues
  111.         //  Also Instructions contain a bunch of data about their surroundings
  112.         //  Probably the best bet to build up a new block instead
  113.         IRBuilder<> builder(op);
  114.         Value *op0 = op->getOperand(0);
  115.         Value *op1 = op->getOperand(1);
  116.         Instruction *op_ = NULL;
  117.         //use appropriate operation
  118.         switch(op->getOpcode()) {
  119.            //case Instruction::Add: op_=BinaryOperator::Create(llvm::Instruction::Sub, op0, op1); break;
  120.             //case Instruction::Add: op_=builder.CreateSub(op0, op1); break;
  121.             case Instruction::Add: op_=BinaryOperator::Create(llvm::Instruction::Sub, op0, op1); break;
  122.             //case Instruction::Sub: op_=builder.CreateAdd(op0, op1); break;
  123.             //case Instruction::Mul: op_=builder.CreateSDiv(op0, op1); break;
  124.             case Instruction::Sub: op_=BinaryOperator::Create(llvm::Instruction::Add, op0, op1); break;
  125.             case Instruction::Mul: op_=BinaryOperator::Create(llvm::Instruction::SDiv, op0, op1); break;
  126.             case Instruction::UDiv: //treat both as signed
  127.             case Instruction::SDiv: op_=BinaryOperator::Create(llvm::Instruction::Mul, op0, op1); break;
  128.             default: errs() << "Unknown\n"; return -1;
  129.         }
  130.         //std::swap(op, op_);
  131.         if(op_) {
  132.             for (auto& U : op->uses()) {
  133.                 errs() << "tryna make a change\n";
  134.                 User *user = U.getUser();
  135.                 user->setOperand(U.getOperandNo(), op_);
  136.             }
  137.         }
  138.         //op->swapOperands() ?
  139.         return 0;
  140.     }
  141.  
  142.     void reverse_subblocks(std::vector<Subblock> subblocks) {
  143.         //reverses the subblocks in place
  144.         //TODO: again, this probably can't be done in place
  145.         //  because Intructions try to reference each other or something
  146.         //  Try to construct a basic block from each subblock's instructions instead,
  147.         //   traversing the vec in reverse order
  148.         auto begin = subblocks.begin();
  149.         auto end = --subblocks.end();
  150.         while(true) {
  151.             errs() << "XXX\n";
  152.             //swap contents of `begin` and `end`
  153.             std::swap(begin->load1, end->load1);
  154.             std::swap(begin->load2, end->load2);
  155.             std::swap(begin->op, end->op);
  156.             std::swap(begin->store, end->store);
  157.  
  158.             ++begin;
  159.             if(begin == end) { break; }
  160.             ++end;
  161.             if(begin == end) { break; }
  162.         }
  163.     }
  164.  
  165.  
  166.     struct Hw2 : public FunctionPass {
  167.         static char ID; // Pass identification, replacement for typeid
  168.         Hw2() : FunctionPass(ID) {}
  169.  
  170.         bool runOnFunction(Function &F) override {
  171.             //only run on the `foo` function
  172.             if(F.getName() != "foo") {
  173.                 return false;
  174.             }
  175.  
  176.             Subblock subblock;
  177.             std::vector<Subblock> subblocks;
  178.  
  179.             for (auto &B : F) {
  180.                 for (auto &I : B) {
  181.                     errs() << "<<"; I.print(errs()); errs() << ">>\n";
  182.                     //cycle through the instructions of this function
  183.                     if (dyn_cast<ReturnInst>(&I)) {
  184.                         break;
  185.                     }
  186.                     int rc = subblock.insert(I);
  187.                     if (rc < 0) {
  188.                         return true;
  189.                     } else if (rc == 1) {
  190.                         errs() << "Found complete subblock\n";
  191.                         errs() << "USED TO BE:\n";
  192.                         subblock.print();
  193.                         subblock.invert();
  194.                         errs() << "BECAME:\n";
  195.                         subblock.print();
  196.                         subblocks.push_back(subblock);
  197.                         subblock.clear();
  198.                     }
  199.                 }
  200.             }
  201.             errs() << "FOO\n";
  202.             for(auto i: subblocks) {
  203.                 i.print();
  204.             }
  205.             //reverse_subblocks(subblocks);
  206.             errs() << "\n\n\nRESULT:\n";
  207.             for(auto i: subblocks) {
  208.                 i.print();
  209.             }
  210.             //for (auto &B : F) {
  211.             //    for (auto &I : B) {
  212.             //        errs() << "<<"; I.print(errs()); errs() << ">>\n";
  213.             //    }
  214.             //}
  215.  
  216.             return true;
  217.         }
  218.     };
  219. }
  220.  
  221.  
  222. char Hw2::ID = 0;
  223. static RegisterPass<Hw2> X("hw2", "HW2: shitty block inverter");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement