Example #1
0
// what a hack
static Function *getStubFunctionForCtorList(Module *m,
                                            GlobalVariable *gv, 
                                            std::string name) {
  assert(!gv->isDeclaration() && !gv->hasInternalLinkage() &&
         "do not support old LLVM style constructor/destructor lists");
  
  std::vector<const Type*> nullary;

  Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(getGlobalContext()), 
						    nullary, false),
				  GlobalVariable::InternalLinkage, 
				  name,
                              m);
  BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "entry", fn);
  
  // From lli:
  // Should be an array of '{ int, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  ConstantArray *arr = dyn_cast<ConstantArray>(gv->getInitializer());
  if (arr) {
    for (unsigned i=0; i<arr->getNumOperands(); i++) {
      ConstantStruct *cs = cast<ConstantStruct>(arr->getOperand(i));
      assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list");
      
      Constant *fp = cs->getOperand(1);      
      if (!fp->isNullValue()) {
        if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp))
          fp = ce->getOperand(0);

        if (Function *f = dyn_cast<Function>(fp)) {
	  CallInst::Create(f, "", bb);
        } else {
          assert(0 && "unable to get function pointer from ctor initializer list");
        }
      }
    }
  }
  
  ReturnInst::Create(getGlobalContext(), bb);

  return fn;
}
Example #2
0
bool CheckInserter::doFinalization(Module &M) {
  // We couldn't directly add an element to a constant array, because doing so
  // changes the type of the constant array.

  // element type of llvm.global_ctors
  StructType *ST = StructType::get(IntType,
                                   PointerType::getUnqual(InitFiniType),
                                   NULL); // end with null

  // Move all existing elements of <GlobalName> to <Constants>.
  vector<Constant *> Constants;
  if (GlobalVariable *GlobalCtors = M.getNamedGlobal("llvm.global_ctors")) {
    ConstantArray *CA = cast<ConstantArray>(GlobalCtors->getInitializer());
    for (unsigned j = 0; j < CA->getNumOperands(); ++j) {
      ConstantStruct *CS = cast<ConstantStruct>(CA->getOperand(j));
      assert(CS->getType() == ST);
      // Assume nobody is using the highest priority, so that <F> will be the
      // first to run as a ctor.
      assert(!cast<ConstantInt>(CS->getOperand(0))->isMinValue(true));
      Constants.push_back(CS);
    }
    GlobalCtors->eraseFromParent();
  }
  // Add <F> with the highest priority.
  Constants.push_back(ConstantStruct::get(ST,
                                          ConstantInt::get(IntType, INT_MIN),
                                          EnterProcess,
                                          NULL));
  // Create the new llvm.global_ctors.
  ArrayType *ArrType = ArrayType::get(ST, Constants.size());
  new GlobalVariable(M,
                     ArrType,
                     true,
                     GlobalValue::AppendingLinkage,
                     ConstantArray::get(ArrType, Constants),
                     "llvm.global_ctors");

  return true;
}
Example #3
0
//----------------------------------------------------------------------------
bool FxCompiler::GetConstant (const TokenArray& tokens,
    const std::string& name, Shader::VariableType type,
    ConstantArray& constants)
{
    std::string::size_type begin, end;

    if (tokens[5].size() < 4
    ||  tokens[5][0] != 'c'
    ||  tokens[5][1] != '['
    ||  (end = tokens[5].find("]", 0)) == std::string::npos)
    {
        ReportError("Expecting 'c[register]' token", &tokens);
        return false;
    }

    // Get the base register for the constant.
    begin = 2; // character after '['
    std::string number = tokens[5].substr(begin, end - begin);
    int baseRegister = atoi(number.c_str());
    if (baseRegister == 0 && number != "0")
    {
        ReportError("Invalid base register", &tokens);
        return false;
    }

    // Get the number of registers used by the constant.
    int numRegistersUsed;
    if (tokens[5].find(",", 0) == std::string::npos)
    {
        // The constant uses one register.
        numRegistersUsed = 1;
    }
    else
    {
        // The constant uses more than one register.
        numRegistersUsed = atoi(tokens[6].c_str());
        if (numRegistersUsed == 0)
        {
            ReportError("Invalid number of registers", &tokens);
            return false;
        }
    }

    Constant constant;
    constant.Name = name;
    constant.Type = type;
    constant.BaseRegister = baseRegister;
    constant.NumRegistersUsed = numRegistersUsed;
    constants.push_back(constant);
    return true;
}
/// GetConstantStringInfo - This function computes the length of a
/// null-terminated C string pointed to by V.  If successful, it returns true
/// and returns the string in Str.  If unsuccessful, it returns false.
bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset,
                                 bool StopAtNul) {
  // If V is NULL then return false;
  if (V == NULL) return false;

  // Look through bitcast instructions.
  if (BitCastInst *BCI = dyn_cast<BitCastInst>(V))
    return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul);
  
  // If the value is not a GEP instruction nor a constant expression with a
  // GEP instruction, then return false because ConstantArray can't occur
  // any other way
  User *GEP = 0;
  if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) {
    GEP = GEPI;
  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
    if (CE->getOpcode() == Instruction::BitCast)
      return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul);
    if (CE->getOpcode() != Instruction::GetElementPtr)
      return false;
    GEP = CE;
  }
  
  if (GEP) {
    // Make sure the GEP has exactly three arguments.
    if (GEP->getNumOperands() != 3)
      return false;
    
    // Make sure the index-ee is a pointer to array of i8.
    const PointerType *PT = cast<PointerType>(GEP->getOperand(0)->getType());
    const ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType());
    if (AT == 0 || AT->getElementType() != Type::Int8Ty)
      return false;
    
    // Check to make sure that the first operand of the GEP is an integer and
    // has value 0 so that we are sure we're indexing into the initializer.
    ConstantInt *FirstIdx = dyn_cast<ConstantInt>(GEP->getOperand(1));
    if (FirstIdx == 0 || !FirstIdx->isZero())
      return false;
    
    // If the second index isn't a ConstantInt, then this is a variable index
    // into the array.  If this occurs, we can't say anything meaningful about
    // the string.
    uint64_t StartIdx = 0;
    if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(2)))
      StartIdx = CI->getZExtValue();
    else
      return false;
    return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset,
                                 StopAtNul);
  }
  
  // The GEP instruction, constant or instruction, must reference a global
  // variable that is a constant and is initialized. The referenced constant
  // initializer is the array that we'll use for optimization.
  GlobalVariable* GV = dyn_cast<GlobalVariable>(V);
  if (!GV || !GV->isConstant() || !GV->hasInitializer())
    return false;
  Constant *GlobalInit = GV->getInitializer();
  
  // Handle the ConstantAggregateZero case
  if (isa<ConstantAggregateZero>(GlobalInit)) {
    // This is a degenerate case. The initializer is constant zero so the
    // length of the string must be zero.
    Str.clear();
    return true;
  }
  
  // Must be a Constant Array
  ConstantArray *Array = dyn_cast<ConstantArray>(GlobalInit);
  if (Array == 0 || Array->getType()->getElementType() != Type::Int8Ty)
    return false;
  
  // Get the number of elements in the array
  uint64_t NumElts = Array->getType()->getNumElements();
  
  if (Offset > NumElts)
    return false;
  
  // Traverse the constant array from 'Offset' which is the place the GEP refers
  // to in the array.
  Str.reserve(NumElts-Offset);
  for (unsigned i = Offset; i != NumElts; ++i) {
    Constant *Elt = Array->getOperand(i);
    ConstantInt *CI = dyn_cast<ConstantInt>(Elt);
    if (!CI) // This array isn't suitable, non-int initializer.
      return false;
    if (StopAtNul && CI->isZero())
      return true; // we found end of string, success!
    Str += (char)CI->getZExtValue();
  }
  
  // The array isn't null terminated, but maybe this is a memcpy, not a strcpy.
  return true;
}
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI, Module& M) {
  if (find(classes.begin(), classes.end(), TI) == classes.end()) {
    SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Adding class " << TI->getName() << "\n");
    classes.push_back(TI);

    // First process the correspoding virtual table. We store the indexes of the primary
    // and secondary vtables, indexed by the corresponding subobject offset. This will allow
    // us to quickly jump to a particular sub-vtable.
    if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
      GlobalVariable* VT = typeInfoToVTable[TI]; 
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n");
      ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer());
      for (int i=0; i<VTinit->getNumOperands(); i++) {
        ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(i));
        for (int j=0; j<VTinitElem->getNumOperands(); j++) {
          // Each sub-vtable is preceded by a reference to the class's type_info instance.
          // (See https://mentorembedded.github.io/cxx-abi/abi.html).
          if (TI == VTinitElem->getOperand(j)->stripPointerCasts()) {
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found TI at index " << i << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Storing mapping " << VT->getName() << " <-> " << TI->getName() << "\n");
            
            // the offset to top is the offset from the vptr pointing to this
            // sub-vtable, back to the top of the object. This will be negative,
            // but the absolute value gives us the offset from the start of the
            // object (i.e. first vptr), to the subobject.
            int offsetToTop = 0;
            if (ConstantExpr* offsetValCast = dyn_cast<ConstantExpr>(VTinitElem->getOperand(j-1)->stripPointerCasts())) {
              ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0));
              offsetToTop = offsetVal->getSExtValue(); // will be 0 for the primary
            }
            if (offsetToTop > 0) {
              report_fatal_error("ERROR: offsetToTop is positive!");
            }
            else {
              offsetToTop *= -1;
            }
            
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n")
            vTableToSecondaryVTableMaps[VT][offsetToTop] = pair<int, int>(i, j+1);
          }
        }
      }
    }
    else {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No vtable found for " << TI->getName() << "\n");
    }

    // Now process the type_info struct, extract direct base class info (what
    // their subobject offsets are, or if they are virtual then their
    // virtual-base-offset-offset)
    if (TI->hasInitializer()) {
      ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer());

      int TInumOperands = TIinit->getNumOperands();
      if (TInumOperands > 2) { // first two operands are vptr and type name
        // we have >= 1 base class(es).
        if (TInumOperands == 3) {
          // abi::__si_class_type_info: single, public, non-virtual base at
          // offset 0
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__si_class_type_info\n");
          GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts());
          classToSubclasses[baseTI].push_back(TI);
          //dbgs() << "  " << *baseTI << "\n";
          classToBaseOffset[TI][baseTI] = 0;
          processTypeInfo(baseTI, M);
        }
        else {
          // abi::__vmi_class_type_info: all other cases
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__vmi_class_type_info\n");
          // (skip over first two additional fields, which are "flags" and "base_count")
          for (int i=4; i<TInumOperands; i+=2) {
            GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts());
            classToSubclasses[baseTI].push_back(TI);
            long offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue();
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset_flags = " << offset_flags << "\n");
            ptrdiff_t offset = offset_flags >> offset_shift;
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset = " << offset << "\n");
            // If this a virtual base class, then we obtain the
            // vbase-offset-offset.  This is the offset from the start of the
            // derived class's (primary) vtable to the location containing the
            // vbase-offset, which is the offset from the start of the object
            // to the virtual base's subobject. Note that virtual base
            // subobjects only exist once and are laid out after all other
            // non-virtual objects. We keep track of the vbase-offset-offset,
            // so that we can find the vbase offset when going down the class
            // hierarchy. (The vbase offset may differ every time but the
            // vbase-offset-offset will remain the same relative to the current
            // class's vtable in subclasses).
            if (offset_flags & virtual_mask) { // is this a virtual base class?
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "virtual base class: " << baseTI->getName() << "\n");
              int vbaseOffsetOffset = offset/sizeof(long); // this should be negative
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-offset: " << vbaseOffsetOffset << "\n");
              classToVBaseOffsetOffset[TI][baseTI] = vbaseOffsetOffset;
              if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
                GlobalVariable* VT = typeInfoToVTable[TI];
                int vbaseOffsetIdx = vTableToSecondaryVTableMaps[VT][0].second+vbaseOffsetOffset;
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-idx: " << vbaseOffsetIdx << "\n");
              }
              else {
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No VTable for " << TI->getName() << "\n");
              }
            }
            else {
              // In the non-virtual base class case, we just record the subobj
              // offset. This is the offset from the start of the derived
              // object to the base class's subobject. We use this information
              // together with the offset-to-top info we obtained from the
              // vtable to find the base class's subvtable. Note that the
              // relative position of the base class subobj within the current
              // derived object will always remain the same, even in
              // subclasses.
              classToBaseOffset[TI][baseTI] = offset;
            }
            //dbgs() << "  " << *baseTI << "\n";
            processTypeInfo(baseTI, M);
          }
        }
      }
    }
Example #6
0
bool SDFix::fixDestructors() {
  bool replaced = false;

  for (GlobalVariable& gv : module->getGlobalList()) {
    if (! sd_isVtableName_ref(gv.getName()))
      continue;
    else if (! gv.hasInitializer())
      continue;

    Constant* init = gv.getInitializer();
    assert(init);
    ConstantArray* vtable = dyn_cast<ConstantArray>(init);
    assert(vtable);

    // get an idea about the virtual function regions
    std::vector<vtbl_pair_t> vtblRegions = findSubVtables(vtable);

    // for each subvtable
    for(unsigned vtblInd = 0; vtblInd < vtblRegions.size(); vtblInd++) {
      // record the destructors used in the vtable
      std::vector<DestructorInfo> destructors(3);

      vtbl_pair_t p = vtblRegions[vtblInd];

      for(unsigned i=p.first; i<p.second; i++) {
        Constant* destructor = sd_getDestructorFunction(vtable->getOperand(i));

        if (destructor == NULL)
          continue;

        // get the type from its name
        unsigned s = destructor->getName().size();
        char type = destructor->getName()[s-3];
        assert('0' <= type && type <= '2');
        unsigned typeInt = type - '0';

        // store it temporarily
        destructors[typeInt] = DestructorInfo(destructor, i);
      }

      // deleting destructor should always be defined
      assert(! destructors[0].needsReplacement());

      DestructorInfo* d1 = &destructors[1];
      DestructorInfo* d2 = &destructors[2];

      // only one of the rest could be undefined
      assert(! d1->needsReplacement() || ! d2->needsReplacement());

      // if complete object destructor is missing...
      if (d1->needsReplacement()) {
        std::string gv2Name = d1->function->getName();
        unsigned l = gv2Name.length();
        gv2Name = gv2Name.replace(l-3, 1, "2");

        Function* f1 = d1->getFunction();
        assert(f1);
        Function* f2 = module->getFunction(gv2Name);
        assert(f2);

        sd_print("Replacing %s with %s inside %s\n",
                 d1->function->getName().data(),
                 gv2Name.c_str(),
                 gv.getName().data());

        f1->replaceAllUsesWith(f2);
        replaced = true;

      // if base object destructor is missing...
      } else if (d2->needsReplacement()) {
        std::string gv1Name = d2->function->getName();
        unsigned l = gv1Name.length();
        gv1Name = gv1Name.replace(l-3, 1, "1");

        Function* f2 = d2->getFunction();
        assert(f2);
        Function* f1 = module->getFunction(gv1Name);
        assert(f1);

        sd_print("Replacing %s with %s inside %s\n",
                 d2->function->getName().data(),
                 gv1Name.c_str(),
                 gv.getName().data());

        f2->replaceAllUsesWith(f1);
        replaced = true;
      }
    }
  }

  return replaced;
}
Example #7
0
//
// Method: postOrderInline()
//
// Description:
//  This methods does a post order traversal of the call graph and performs
//  bottom-up inlining of the DSGraphs.
//
void
BUDataStructures::postOrderInline (Module & M) {
  // Variables used for Tarjan SCC-finding algorithm.  These are passed into
  // the recursive function used to find SCCs.
  std::vector<const Function*> Stack;
  std::map<const Function*, unsigned> ValMap;
  unsigned NextID = 1;


  // Do post order traversal on the global ctors. Use this information to update
  // the globals graph.
  const char *Name = "llvm.global_ctors";
  GlobalVariable *GV = M.getNamedGlobal(Name);
  if (GV && !(GV->isDeclaration()) && !(GV->hasLocalLinkage())) {
    // Should be an array of '{ int, void ()* }' structs.  The first value is
    // the init priority, which we ignore.
    ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
    if (InitList) {
      for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
        if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
          if (CS->getNumOperands() != 2)
            break; // Not array of 2-element structs.
          Constant *FP = CS->getOperand(1);
          if (FP->isNullValue())
            break;  // Found a null terminator, exit.

          if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
            if (CE->isCast())
              FP = CE->getOperand(0);
          Function *F = dyn_cast<Function>(FP);
          if (F && !F->isDeclaration() && !ValMap.count(F)) {
            calculateGraphs(F, Stack, NextID, ValMap);
            CloneAuxIntoGlobal(getDSGraph(*F));
          }
        }
      GlobalsGraph->removeTriviallyDeadNodes();
      GlobalsGraph->maskIncompleteMarkers();

      // Mark external globals incomplete.
      GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals);
      GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
      GlobalsGraph->computeIntPtrFlags();

      //
      // Create equivalence classes for aliasing globals so that we only need to
      // record one global per DSNode.
      //
      formGlobalECs();
      // propogte information calculated
      // from the globals graph to the other graphs.
      for (Module::iterator F = M.begin(); F != M.end(); ++F) {
        if (!(F->isDeclaration())){
          DSGraph *Graph  = getDSGraph(*F);
          cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes |
                           DSGraph::DontCloneAuxCallNodes);
          Graph->buildCallGraph(callgraph, GlobalFunctionList, filterCallees);
          Graph->maskIncompleteMarkers();
          Graph->markIncompleteNodes(DSGraph::MarkFormalArgs |
                                     DSGraph::IgnoreGlobals);
          Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
          Graph->computeIntPtrFlags();
        }
      }
    }
  }

  //
  // Start the post order traversal with the main() function.  If there is no
  // main() function, don't worry; we'll have a separate traversal for inlining
  // graphs for functions not reachable from main().
  //
  Function *MainFunc = M.getFunction ("main");
  if (MainFunc && !MainFunc->isDeclaration()) {
    calculateGraphs(MainFunc, Stack, NextID, ValMap);
    CloneAuxIntoGlobal(getDSGraph(*MainFunc));
  }

  //
  // Calculate the graphs for any functions that are unreachable from main...
  //
  for (Function &F : M)
    if (!F.isDeclaration() && !ValMap.count(&F)) {
      if (MainFunc)
        DEBUG(errs() << debugname << ": Function unreachable from main: "
        << F.getName() << "\n");
      calculateGraphs(&F, Stack, NextID, ValMap);     // Calculate all graphs.
      CloneAuxIntoGlobal(getDSGraph(F));

      // Mark this graph as processed.  Do this by finding all functions
      // in the graph that map to it, and mark them visited.
      // Note that this really should be handled neatly by calculateGraphs
      // itself, not here.  However this catches the worst offenders.
      DSGraph *G = getDSGraph(F);
      for(DSGraph::retnodes_iterator RI = G->retnodes_begin(),
          RE = G->retnodes_end(); RI != RE; ++RI) {
        if (getDSGraph(*RI->first) == G) {
          if (!ValMap.count(RI->first))
            ValMap[RI->first] = ~0U;
          else
            assert(ValMap[RI->first] == ~0U);
        }
      }
    }
  return;
}
Example #8
0
//----------------------------------------------------------------------------
bool FxCompiler::UpdateShader (Shader* shader, const Program& program,
    InputArray& inputs, OutputArray& outputs, ConstantArray& constants,
    SamplerArray& samplers)
{
    int numInputs = (int)inputs.size();
    if (numInputs != shader->GetNumInputs())
    {
        ReportError("Mismatch in number of inputs.\n");
        return false;
    }

    int numOutputs = (int)outputs.size();
    if (numOutputs != shader->GetNumOutputs())
    {
        ReportError("Mismatch in number of outputs.\n");
        return false;
    }

    int numConstants = (int)constants.size();
    if (numConstants != shader->GetNumConstants())
    {
        ReportError("Mismatch in number of constants.\n");
        return false;
    }

    int numSamplers = (int)samplers.size();
    if (numSamplers != shader->GetNumSamplers())
    {
        ReportError("Mismatch in number of samplers.\n");
        return false;
    }

    std::string message;
    int i;
    for (i = 0; i < numInputs; ++i)
    {
        Input& input = inputs[i];
        if (input.Name != shader->GetInputName(i))
        {
            message =  "Mismatch in input names '" +
                input.Name +
                "' and '" +
                shader->GetInputName(i);

            ReportError(message);
            return false;
        }
        if (input.Type != shader->GetInputType(i))
        {
            message =  "Mismatch in input types '" +
                msVTName[input.Type] +
                "' and '" +
                msVTName[shader->GetInputType(i)];

            ReportError(message);
            return false;
        }
        if (input.Semantic != shader->GetInputSemantic(i))
        {
            message =  "Mismatch in input semantics '" +
                msVSName[input.Semantic] +
                "' and '" +
                msVSName[shader->GetInputSemantic(i)];

            ReportError(message);
            return false;
        }
    }

    for (i = 0; i < numOutputs; ++i)
    {
        Output& output = outputs[i];
        if (output.Name != shader->GetOutputName(i))
        {
            message =  "Mismatch in output names '" +
                output.Name +
                "' and '" +
                shader->GetOutputName(i);

            ReportError(message);
            return false;
        }
        if (output.Type != shader->GetOutputType(i))
        {
            message =  "Mismatch in output types '" +
                msVTName[output.Type] +
                "' and '" +
                msVTName[shader->GetOutputType(i)];

            ReportError(message);
            return false;
        }
        if (output.Semantic != shader->GetOutputSemantic(i))
        {
            message =  "Mismatch in output semantics '" +
                msVSName[output.Semantic] +
                "' and '" +
                msVSName[shader->GetOutputSemantic(i)];

            ReportError(message);
            return false;
        }
    }

    for (i = 0; i < numConstants; ++i)
    {
        Constant& constant = constants[i];
        if (constant.Name != shader->GetConstantName(i))
        {
            message =  "Mismatch in constant names '" +
                constant.Name +
                "' and '" +
                shader->GetConstantName(i);

            ReportError(message);
            return false;
        }
        if (constant.NumRegistersUsed != shader->GetNumRegistersUsed(i))
        {
            char number0[8], number1[8];
            sprintf(number0, "%d", constant.NumRegistersUsed);
            sprintf(number1, "%d", shader->GetNumRegistersUsed(i));
            message =  "Mismatch in constant registers used '" +
                std::string(number0) +
                "' and '" +
                std::string(number1);

            ReportError(message);
            return false;
        }
        shader->SetBaseRegister(mActiveProfile, i, constant.BaseRegister);
    }

    for (i = 0; i < numSamplers; ++i)
    {
        Sampler& sampler = samplers[i];
        if (sampler.Name != shader->GetSamplerName(i))
        {
            message =  "Mismatch in sampler names '" +
                sampler.Name +
                "' and '" +
                shader->GetSamplerName(i);

            ReportError(message);
            return false;
        }
        if (sampler.Type != shader->GetSamplerType(i))
        {
            message =  "Mismatch in sampler types '" +
                msSTName[sampler.Type] +
                "' and '" +
                msSTName[shader->GetSamplerType(i)];

            ReportError(message);
            return false;
        }
        shader->SetTextureUnit(mActiveProfile, i, sampler.Unit);
    }

    shader->SetProgram(mActiveProfile, program.Text);
    return true;
}
Example #9
0
//----------------------------------------------------------------------------
bool FxCompiler::Process (const Program& program, InputArray& inputs,
    OutputArray& outputs, ConstantArray& constants, SamplerArray& samplers)
{
    // Variable lines are one of the following:
    //   var TYPE NAME : $vin.SEMANTIC  : inputType           : index : 1
    //   var TYPE NAME : $vout.SEMANTIC : outputType          : index : 1
    //   var TYPE NAME :                : c[REGISTER]         : index : 1
    //   var TYPE NAME :                : c[REGISTER], NUMREG : index : 1
    //   var TYPE NAME :                : texunit UNITNUMBER  : -1    : 1
    // The last field is "used", a value of "0" or "1".  However, the parser
    // stored in 'program' only those variables with a used value "1".  The
    // all-capitals identifiers are needed by the Wild Magic FX system.

    TokenArrays::const_iterator iter = program.Variables.begin();
    TokenArrays::const_iterator end = program.Variables.end();
    for (/**/; iter != end; ++iter)
    {
        const TokenArray& tokens = *iter;

        // The token array has 10 or 11 tokens.
        if (tokens.size() < 10 || tokens.size() > 11)
        {
            ReportError("Invalid number of tokens", &tokens);
            return false;
        }

        // Get the variable type.
        Shader::VariableType vartype = Shader::VT_NONE;
        Shader::SamplerType samtype = Shader::ST_NONE;
        std::string::size_type begin = tokens[1].find("sampler", 0);
        if (begin != std::string::npos)
        {
            SamplerTypeMap::iterator iter = mSamplerTypes.find(tokens[1]);
            if (iter == mSamplerTypes.end())
            {
                ReportError("Invalid sampler type", &tokens);
                return false;
            }
            samtype = iter->second;
        }
        else
        {
            VariableTypeMap::iterator iter = mVariableTypes.find(tokens[1]);
            if (iter == mVariableTypes.end())
            {
                ReportError("Invalid variable type", &tokens);
                return false;
            }
            vartype = iter->second;
        }

        // Get the variable name.
        std::string name = tokens[2];

        // Test whether the variable is a singleton or was declared as an
        // array.  If it is an array, we need to determine how many registers
        // it uses.  This requires processing variable lines with the same
        // variable index.
        bool varArray;
        begin = name.find("[", 0);
        if (begin != std::string::npos)
        {
            varArray = true;
            name = name.substr(0, begin);  // strip off "[register]"
        }
        else
        {
            varArray = false;
        }

        // Get the separator before the classifier.
        if (tokens[3] != ":")
        {
            ReportError("Expecting separator character at index 3", &tokens);
            return false;
        }

        // Get the classifier.
        begin = tokens[4].find("$vin.", 0);
        if (begin != std::string::npos)
        {
            // The variable is a shader input.
            if (!GetInput(tokens, name, vartype, inputs))
            {
                return false;
            }
            continue;
        }

        begin = tokens[4].find("$vout.", 0);
        if (begin != std::string::npos)
        {
            // The variable is a shader output.
            if (!GetOutput(tokens, name, vartype, outputs))
            {
                return false;
            }
            continue;
        }

        if (tokens[4] == ":")
        {
            begin = tokens[1].find("sampler", 0);
            if (begin != std::string::npos)
            {
                // The variable is a shader sampler.
                if (!GetSampler(tokens, name, samtype, samplers))
                {
                    return false;
                }
            }
            else
            {
                // The variable is a shader constant.
                if (varArray)
                {
                    if (constants.size() > 0 && name == constants.back().Name)
                    {
                        // This is another occurrence of the array variable.
                        // Just increment the register count.
                        ++constants.back().NumRegistersUsed;
                    }
                    else
                    {
                        // Create the constant with the first occurrence of
                        // the array variable.
                        if (!GetConstant(tokens, name, vartype, constants))
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    if (!GetConstant(tokens, name, vartype, constants))
                    {
                        return false;
                    }
                }
            }
            continue;
        }

        ReportError("Failed to find classifier", &tokens);
        return false;
    }

    return true;
}
Example #10
0
SandboxVector SandboxUtils::findSandboxes(Module& M) {
  FunctionIntMap funcToOverhead;
  FunctionIntMap funcToClearances;
  map<Function*,string> funcToSandboxName;
  map<string,FunctionSet> sandboxNameToEntryPoints;
  StringSet ephemeralSandboxes;

  SandboxVector sandboxes;

  // function-level annotations of sandboxed code
  Regex *sboxPerfRegex = new Regex("perf_overhead_\\(([0-9]{1,2})\\)", true);
  SmallVector<StringRef, 4> matches;
  if (GlobalVariable* lga = M.getNamedGlobal("llvm.global.annotations")) {
    ConstantArray* lgaArray = dyn_cast<ConstantArray>(lga->getInitializer()->stripPointerCasts());
    for (User::op_iterator i=lgaArray->op_begin(), e = lgaArray->op_end(); e!=i; i++) {
      ConstantStruct* lgaArrayElement = dyn_cast<ConstantStruct>(i->get());

      // get the annotation value first
      GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(lgaArrayElement->getOperand(1)->stripPointerCasts());
      ConstantDataArray* annotationStrArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer());
      StringRef annotationStrArrayCString = annotationStrArray->getAsCString();
      GlobalValue* annotatedVal = dyn_cast<GlobalValue>(lgaArrayElement->getOperand(0)->stripPointerCasts());
      if (isa<Function>(annotatedVal)) {
        Function* annotatedFunc = dyn_cast<Function>(annotatedVal);
        StringRef sandboxName;
        if (annotationStrArrayCString.startswith(SANDBOX_PERSISTENT) || annotationStrArrayCString.startswith(SANDBOX_EPHEMERAL)) {
          sandboxEntryPoints.insert(annotatedFunc);
          outs() << INDENT_1 << "Found sandbox entrypoint " << annotatedFunc->getName() << "\n";
          outs() << INDENT_2 << "Annotation string: " << annotationStrArrayCString << "\n";
          if (annotationStrArrayCString.startswith(SANDBOX_PERSISTENT)) {
            sandboxName = annotationStrArrayCString.substr(strlen(SANDBOX_PERSISTENT)+1);
          }
          else if (annotationStrArrayCString.startswith(SANDBOX_EPHEMERAL)) {
            sandboxName = annotationStrArrayCString.substr(strlen(SANDBOX_EPHEMERAL)+1);
            ephemeralSandboxes.insert(sandboxName);
          }
          outs() << INDENT_2 << "Sandbox name: " << sandboxName << "\n";
          if (funcToSandboxName.find(annotatedFunc) != funcToSandboxName.end()) {
            outs() << INDENT_1 << "*** Error: Function " << annotatedFunc->getName() << " is already an entrypoint for another sandbox\n";
          }
          else {
            funcToSandboxName[annotatedFunc] = sandboxName;
            sandboxNameToEntryPoints[sandboxName].insert(annotatedFunc);
          }
        }
        else if (sboxPerfRegex->match(annotationStrArrayCString, &matches)) {
          int overhead;
          outs() << INDENT_2 << "Threshold set to " << matches[1].str() <<
                  "%\n";
          matches[1].getAsInteger(0, overhead);
          funcToOverhead[annotatedFunc] = overhead;
        }
        else if (annotationStrArrayCString.startswith(CLEARANCE)) {
          StringRef className = annotationStrArrayCString.substr(strlen(CLEARANCE)+1);
          outs() << INDENT_2 << "Sandbox has clearance for \"" << className << "\"\n";
          ClassifiedUtils::assignBitIdxToClassName(className);
          funcToClearances[annotatedFunc] |= (1 << ClassifiedUtils::getBitIdxFromClassName(className));
        }
      }
    }
  }

  // TODO: sanity check overhead and clearance annotations

  // Combine all annotation information for function-level sandboxes to create Sandbox instances
  for (pair<string,FunctionSet> p : sandboxNameToEntryPoints) {
    string sandboxName = p.first;
    FunctionSet entryPoints = p.second;
    int idx = assignBitIdxToSandboxName(sandboxName);
    int overhead = 0;
    int clearances = 0; 
    bool persistent = find(ephemeralSandboxes.begin(), ephemeralSandboxes.end(), sandboxName) == ephemeralSandboxes.end();

    // set overhead and clearances; any of the entry points could be annotated
    for (Function* entryPoint : entryPoints) {
      if (funcToOverhead.find(entryPoint) != funcToOverhead.end()) {
        overhead = funcToOverhead[entryPoint];
      }
      if (funcToClearances.find(entryPoint) != funcToClearances.end()) {
        clearances = funcToClearances[entryPoint];
      }
    }

		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Creating new Sandbox instance for " << sandboxName << "\n");
    sandboxes.push_back(new Sandbox(sandboxName, idx, entryPoints, persistent, M, overhead, clearances));
		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Created new Sandbox instance\n");
  }

  /*
  for (map<Function*,string>::iterator I=funcToSandboxName.begin(), E=funcToSandboxName.end(); I!=E; I++) {
    Function* entryPoint = I->first;
    string sandboxName = I->second;
    int idx = assignBitIdxToSandboxName(sandboxName);
    int overhead = funcToOverhead[entryPoint];
    int clearances = funcToClearances[entryPoint];
    bool persistent = find(ephemeralSandboxes.begin(), ephemeralSandboxes.end(), entryPoint) == ephemeralSandboxes.end();
		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Creating new Sandbox instance\n");
    sandboxes.push_back(new Sandbox(sandboxName, idx, entryPoint, persistent, M, overhead, clearances));
		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Created new Sandbox instance\n");
  }
  */

  // Handle sandboxed code regions, i.e. start_sandboxed_code(N) and end_sandboxed_code(N) blocks 
  if (Function* SboxStart = M.getFunction("llvm.annotation.i32")) {
    for (User* U : SboxStart->users()) {
      if (IntrinsicInst* annotCall = dyn_cast<IntrinsicInst>(U)) {
        GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(annotCall->getOperand(1)->stripPointerCasts());
        ConstantDataArray* annotationStrValArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer());
        StringRef annotationStrValCString = annotationStrValArray->getAsCString();
        
        if (annotationStrValCString.startswith(SOAAP_SANDBOX_REGION_START)) {
          StringRef sandboxName = annotationStrValCString.substr(strlen(SOAAP_SANDBOX_REGION_START)+1); //+1 because of _
          SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_3 << "Found start of sandboxed code region: "; annotCall->dump(););
          InstVector sandboxedInsts;
          findAllSandboxedInstructions(annotCall, sandboxName, sandboxedInsts);
          int idx = assignBitIdxToSandboxName(sandboxName);
          sandboxes.push_back(new Sandbox(sandboxName, idx, sandboxedInsts, false, M)); //TODO: obtain persistent/ephemeral information in a better way (currently we obtain it from the creation point)
        }
      }
Example #11
0
File: init.cpp Project: aulwes/Byfl
    /**
     * This function creates a module constructor function to create the
     * map from function keys to function names.  This function will be
     * automatically called when the module is loaded.
     *
     * The code was generated by using clang on a test file. The test
     * file looked like (foo.cc):
     * __attribute__((constructor))
     * static void init()
     * {
     * }
     *
     * Then, run:
     * 1. clang -S -emit-llvm -c foo.cc
     * 2. llc -march=cpp foo.bc -o foo.lc
     * The output foo.lc provides code for generating a ctor using LLVM.
     *
     */
    void BytesFlops::initializeKeyMap(Module& module)
    {
        if ( module.getFunction("func_key_map_ctor") )
            return;

        LLVMContext& ctx = module.getContext();

        // Type Definitions
        std::vector<Type*>StructTy_1_fields;
        StructTy_1_fields.push_back(IntegerType::get(ctx, 32));
        std::vector<Type*>FuncTy_3_args;

        FunctionType* FuncTy_3 = FunctionType::get(
                                /*Result=*/   Type::getVoidTy(ctx),
                                /*Params=*/   FuncTy_3_args,
                                /*isVarArg=*/ false);

        PointerType* PointerTy_2 = PointerType::get(FuncTy_3, 0);

        StructTy_1_fields.push_back(PointerTy_2);

        StructType *
        StructTy_1 = StructType::get(ctx, StructTy_1_fields,
                                     /*isPacked=*/false);

        ArrayType* ArrayTy_0 = NULL;

        // Function Declarations
        func_map_ctor = Function::Create(
                        /*Type=*/FuncTy_3,
                        /*Linkage=*/GlobalValue::InternalLinkage,
                        /*Name=*/"func_key_map_ctor", &module);
        func_map_ctor->setCallingConv(CallingConv::C);

        AttributeSet func__ZL4initv_PAL;
        SmallVector<AttributeSet, 4> Attrs;
        AttributeSet PAS;
        AttrBuilder B;
        B.addAttribute(Attribute::NoUnwind);
        B.addAttribute(Attribute::UWTable);
        PAS = AttributeSet::get(ctx, ~0U, B);

        Attrs.push_back(PAS);
        func__ZL4initv_PAL = AttributeSet::get(ctx, Attrs);
        func_map_ctor->setAttributes(func__ZL4initv_PAL);

        // Global Variable Declarations
        // Constant Definitions
        std::vector<Constant*> ctor_elems;
        std::vector<Constant*> const_struct_8_fields;
        ConstantInt* const_int32_9 = ConstantInt::get(ctx, APInt(32, StringRef("65535"), 10));
        const_struct_8_fields.push_back(const_int32_9);
        const_struct_8_fields.push_back(func_map_ctor);
        Constant* const_struct_8 = ConstantStruct::get(StructTy_1, const_struct_8_fields);
        ctor_elems.push_back(const_struct_8);

        GlobalVariable* llvm_global_ctors;

        /**
         * Add our constructor to the list of global constructors for the
         * module.  It's possible that a module already contains a ctor.
         */
        GlobalVariable*
        current_ctors = module.getGlobalVariable("llvm.global_ctors");
        if ( !current_ctors )
        {
            ArrayTy_0 = ArrayType::get(StructTy_1, 1);
        }
        else
        {
            // there are existing ctors, and the initializer points to them.
            // add ours to the initializer list (actually, we create a new
            // initializer list and add the existing ones to it).
            Constant * initializer = current_ctors->getInitializer();

            ConstantArray *
            ar = llvm::dyn_cast<ConstantArray>(initializer);
            assert( ar );

            int cnt = 0;
            Constant *
            elt = ar->getAggregateElement(cnt);

            // add existing ctors to new initializer list, and get rid
            // of the old one.
            while ( elt )
            {
                assert( llvm::dyn_cast<ConstantStruct>(elt) );
                ctor_elems.push_back(elt);
                cnt++;
                elt = ar->getAggregateElement(cnt);
            }
            ArrayTy_0 = ArrayType::get(StructTy_1, ctor_elems.size());
            current_ctors->eraseFromParent();
        }

        llvm_global_ctors = new GlobalVariable(/*Module=*/module,
                              /*Type=*/       ArrayTy_0,
                              /*isConstant=*/ false,
                              /*Linkage=*/    GlobalValue::AppendingLinkage,
                              /*Initializer=*/0, // has initializer, specified below
                              /*Name=*/       "llvm.global_ctors");


        Constant* ctor_array = ConstantArray::get(ArrayTy_0, ctor_elems);

        // Global Variable Definitions
        llvm_global_ctors->setInitializer(ctor_array);
    }
Example #12
0
void PrivilegedCallAnalysis::doAnalysis(Module& M, SandboxVector& sandboxes) {
  // first find all methods annotated as being privileged and then check calls within sandboxes
  if (GlobalVariable* lga = M.getNamedGlobal("llvm.global.annotations")) {
    ConstantArray* lgaArray = dyn_cast<ConstantArray>(lga->getInitializer()->stripPointerCasts());
    for (User::op_iterator i=lgaArray->op_begin(), e = lgaArray->op_end(); e!=i; i++) {
      ConstantStruct* lgaArrayElement = dyn_cast<ConstantStruct>(i->get());

      // get the annotation value first
      GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(lgaArrayElement->getOperand(1)->stripPointerCasts());
      ConstantDataArray* annotationStrArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer());
      StringRef annotationStrArrayCString = annotationStrArray->getAsCString();

      GlobalValue* annotatedVal = dyn_cast<GlobalValue>(lgaArrayElement->getOperand(0)->stripPointerCasts());
      if (isa<Function>(annotatedVal)) {
        Function* annotatedFunc = dyn_cast<Function>(annotatedVal);
        if (annotationStrArrayCString == SOAAP_PRIVILEGED) {
          outs() << "   Found function: " << annotatedFunc->getName() << "\n";
          privAnnotFuncs.push_back(annotatedFunc);
        }
      }
    }
  }          

  // now check calls within sandboxes
  for (Function* privilegedFunc : privAnnotFuncs) {
    for (User* U : privilegedFunc->users()) {
      if (CallInst* C = dyn_cast<CallInst>(U)) {
        Function* enclosingFunc = C->getParent()->getParent();
        for (Sandbox* S : sandboxes) {
          if (!S->hasCallgate(privilegedFunc) && S->containsFunction(enclosingFunc)) {
            outs() << " *** Sandbox \"" << S->getName() << "\" calls privileged function \"" << privilegedFunc->getName() << "\" that they are not allowed to. If intended, annotate this permission using the __soaap_callgates annotation.\n";
            if (MDNode *N = C->getMetadata("dbg")) {  // Here I is an LLVM instruction
              DILocation Loc(N);                      // DILocation is in DebugInfo.h
              unsigned Line = Loc.getLineNumber();
              StringRef File = Loc.getFilename();
              outs() << " +++ Line " << Line << " of file " << File << "\n";
            }
          }
        }
      }
    }
  }

  /*
  for (Sandbox* S : sandboxes) {
    FunctionVector callgates = S->getCallgates();
    for (Function* F : S->getFunctions()) {
      for (BasicBlock& BB : F->getBasicBlockList()) {
        for (Instruction& I : BB.getInstList()) {
          if (CallInst* C = dyn_cast<CallInst>(&I)) {
            if (Function* Target = C->getCalledFunction()) {
              if (find(privAnnotFuncs.begin(), privAnnotFuncs.end(), Target) != privAnnotFuncs.end()) {
                // check if this sandbox is allowed to call the privileged function
                DEBUG(dbgs() << "   Found privileged call: "); 
                DEBUG(C->dump());
                if (find(callgates.begin(), callgates.end(), Target) == callgates.end()) {
                  outs() << " *** Sandbox \"" << S->getName() << "\" calls privileged function \"" << Target->getName() << "\" that they are not allowed to. If intended, annotate this permission using the __soaap_callgates annotation.\n";
                  if (MDNode *N = C->getMetadata("dbg")) {  // Here I is an LLVM instruction
                    DILocation Loc(N);                      // DILocation is in DebugInfo.h
                    unsigned Line = Loc.getLineNumber();
                    StringRef File = Loc.getFilename();
                    outs() << " +++ Line " << Line << " of file " << File << "\n";
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  */
}