liberty/lib/SLAMP/SLAMP.cpp
/// handle each instruction (load, store, callbase) in the targeted loop
handle each instruction (load, store, callbase) in the targeted loop
handle each instruction ( load store callbase ) in the targeted loop
void SLAMP::instrumentLoopInst(Module &m, Instruction *inst, uint32_t id) {
  const DataLayout &DL = m.getDataLayout();
  if (id == 0) 
    return;
  string lf_name[] = {"SLAMP_load1", "SLAMP_load2", "SLAMP_load4",
                      "SLAMP_load8", "SLAMP_loadn"};
  vector<Function *> lf(5);
  for (unsigned i = 0; i < 5; i++) {
    lf[i] = cast<Function>(
        m.getOrInsertFunction(lf_name[i], Void, I32, I64, I32, I64)
            .getCallee());
  }
  string sf_name[] = {"SLAMP_store1", "SLAMP_store2", "SLAMP_store4",
                      "SLAMP_store8", "SLAMP_storen"};
  vector<Function *> sf(5);
  for (unsigned i = 0; i < 4; i++) {
    sf[i] = cast<Function>(
        m.getOrInsertFunction(sf_name[i], Void, I32, I64).getCallee());
  }
  sf[4] = cast<Function>(
      m.getOrInsertFunction(sf_name[4], Void, I32, I64, I64).getCallee());
  auto *push = cast<Function>(
      m.getOrInsertFunction("SLAMP_push", Void, I32).getCallee());
  auto *pop =
      cast<Function>(m.getOrInsertFunction("SLAMP_pop", Void).getCallee());
  if (auto *li = dyn_cast<LoadInst>(inst)) {
    InstInsertPt pt = InstInsertPt::After(li);
    Value *ptr = li->getPointerOperand();
    vector<Value *> args;
    args.push_back(ConstantInt::get(I32, id));
    args.push_back(castToInt64Ty(ptr, pt));
    size_t size;
    int index = getIndex(cast<PointerType>(ptr->getType()), size, DL);
    if (index == 4) {
      args.push_back(ConstantInt::get(I32, id));
      args.push_back(ConstantInt::get(I64, size));
    } else {
      args.push_back(ConstantInt::get(I32, id));
      args.push_back(castToInt64Ty(li, pt));
    }
    pt << CallInst::Create(lf[index], args);
  } else if (auto *si = dyn_cast<StoreInst>(inst)) {
    InstInsertPt pt = InstInsertPt::After(si);
    Value *ptr = si->getPointerOperand();
    vector<Value *> args;
    args.push_back(ConstantInt::get(I32, id));
    args.push_back(castToInt64Ty(ptr, pt));
    size_t size;
    int index = getIndex(cast<PointerType>(ptr->getType()), size, DL);
    if (index == 4) {
      args.push_back(ConstantInt::get(I64, size));
    }
    pt << CallInst::Create(sf[index], args);
  } else if (auto *ci = dyn_cast<CallBase>(inst)) {
    vector<Value *> args;
    args.push_back(ConstantInt::get(I32, id));
    InstInsertPt pt = InstInsertPt::Before(ci);
    pt << CallInst::Create(push, args);
    if (isa<CallInst>(inst)) {
      pt = InstInsertPt::After(ci);
      pt << CallInst::Create(pop);
    } else if (auto *invokeI = dyn_cast<InvokeInst>(inst)) {
      auto insertPop = [&pop](BasicBlock* entry){
        InstInsertPt pt;
        if (isa<LandingPadInst>(entry->getFirstNonPHI()))
          pt = InstInsertPt::After(entry->getFirstNonPHI());
        else
          pt = InstInsertPt::Before(entry->getFirstNonPHI());
        pt << CallInst::Create(pop);
      };
      insertPop(invokeI->getNormalDest());
      insertPop(invokeI->getUnwindDest());
    } else {
      assert(false && "Call but not CallInst nor InvokeInst");
    }
  }
}
void SLAMP :: instrumentLoopInst ( Module & m , Instruction * inst , uint32_t id ) { const DataLayout & DL = m . getDataLayout ( ) ; if ( id == 0 ) return ; string lf_name [ ] = { " " , " " , " " , " " , " " } ; vector < Function * > lf ( 5 ) ; for ( unsigned i = 0 ; i < 5 ; i ++ ) { lf [ i ] = cast < Function > ( m . getOrInsertFunction ( lf_name [ i ] , Void , I32 , I64 , I32 , I64 ) . getCallee ( ) ) ; } string sf_name [ ] = { " " , " " , " " , " " , " " } ; vector < Function * > sf ( 5 ) ; for ( unsigned i = 0 ; i < 4 ; i ++ ) { sf [ i ] = cast < Function > ( m . getOrInsertFunction ( sf_name [ i ] , Void , I32 , I64 ) . getCallee ( ) ) ; } sf [ 4 ] = cast < Function > ( m . getOrInsertFunction ( sf_name [ 4 ] , Void , I32 , I64 , I64 ) . getCallee ( ) ) ; auto * push = cast < Function > ( m . getOrInsertFunction ( " " , Void , I32 ) . getCallee ( ) ) ; auto * pop = cast < Function > ( m . getOrInsertFunction ( " " , Void ) . getCallee ( ) ) ; if ( auto * li = dyn_cast < LoadInst > ( inst ) ) { InstInsertPt pt = InstInsertPt :: After ( li ) ; Value * ptr = li -> getPointerOperand ( ) ; vector < Value * > args ; args . push_back ( ConstantInt :: get ( I32 , id ) ) ; args . push_back ( castToInt64Ty ( ptr , pt ) ) ; size_t size ; int index = getIndex ( cast < PointerType > ( ptr -> getType ( ) ) , size , DL ) ; if ( index == 4 ) { args . push_back ( ConstantInt :: get ( I32 , id ) ) ; args . push_back ( ConstantInt :: get ( I64 , size ) ) ; } else { args . push_back ( ConstantInt :: get ( I32 , id ) ) ; args . push_back ( castToInt64Ty ( li , pt ) ) ; } pt << CallInst :: Create ( lf [ index ] , args ) ; } else if ( auto * si = dyn_cast < StoreInst > ( inst ) ) { InstInsertPt pt = InstInsertPt :: After ( si ) ; Value * ptr = si -> getPointerOperand ( ) ; vector < Value * > args ; args . push_back ( ConstantInt :: get ( I32 , id ) ) ; args . push_back ( castToInt64Ty ( ptr , pt ) ) ; size_t size ; int index = getIndex ( cast < PointerType > ( ptr -> getType ( ) ) , size , DL ) ; if ( index == 4 ) { args . push_back ( ConstantInt :: get ( I64 , size ) ) ; } pt << CallInst :: Create ( sf [ index ] , args ) ; } else if ( auto * ci = dyn_cast < CallBase > ( inst ) ) { vector < Value * > args ; args . push_back ( ConstantInt :: get ( I32 , id ) ) ; InstInsertPt pt = InstInsertPt :: Before ( ci ) ; pt << CallInst :: Create ( push , args ) ; if ( isa < CallInst > ( inst ) ) { pt = InstInsertPt :: After ( ci ) ; pt << CallInst :: Create ( pop ) ; } else if ( auto * invokeI = dyn_cast < InvokeInst > ( inst ) ) { auto insertPop = [ & pop ] ( BasicBlock * entry ) { InstInsertPt pt ; if ( isa < LandingPadInst > ( entry -> getFirstNonPHI ( ) ) ) pt = InstInsertPt :: After ( entry -> getFirstNonPHI ( ) ) ; else pt = InstInsertPt :: Before ( entry -> getFirstNonPHI ( ) ) ; pt << CallInst :: Create ( pop ) ; } ; insertPop ( invokeI -> getNormalDest ( ) ) ; insertPop ( invokeI -> getUnwindDest ( ) ) ; } else { assert ( false && " " ) ; } } }
handle each instruction (load, store, callbase) in the targeted loop
handle each instruction ( load store callbase ) in the targeted loop
// assert(id < INST_ID_BOUND); // instrumented instructions // --- loads // load1-8 the last argument is the value, use to do prediction // loadn the last argument is the length // --- stores // --- calls // need to handle call and invoke // for invoke, need to find the two paths and add pop // FIXME: will generate mulitiple `slamp_pop` after the landing pad //        Fine for now because `slamp_pop` only set the context to 0