Example #1
0
llvm::GlobalVariable* JitCodeSpecializer::_clone_global_variable(SpecializationContext& context,
                                                                 const llvm::GlobalVariable& global_variable) const {
  // If the global variable already exists in the module, there is no point in cloning it again
  if (auto global = context.module->getGlobalVariable(global_variable.getName())) {
    return global;
  }

  // Create a new global variable with the same type, attributes, and properties
  const auto cloned_global = llvm::dyn_cast<llvm::GlobalVariable>(
      context.module->getOrInsertGlobal(global_variable.getName(), global_variable.getValueType()));
  cloned_global->setLinkage(global_variable.getLinkage());
  cloned_global->setThreadLocalMode(global_variable.getThreadLocalMode());
  cloned_global->copyAttributesFrom(&global_variable);

  if (!global_variable.isDeclaration()) {
    if (global_variable.hasInitializer()) {
      // Instruct LLVM to perform the cloning of the actual value (i.e., initializer) of the variable
      cloned_global->setInitializer(llvm::MapValue(global_variable.getInitializer(), context.llvm_value_map));
    }

    // Clone LLVM metadata for the global variable
    llvm::SmallVector<std::pair<uint32_t, llvm::MDNode*>, 1> metadata_nodes;
    global_variable.getAllMetadata(metadata_nodes);
    for (const auto& metadata_node : metadata_nodes) {
      cloned_global->addMetadata(metadata_node.first,
                                 *MapMetadata(metadata_node.second, context.llvm_value_map, llvm::RF_MoveDistinctMDs));
    }
  }

  return cloned_global;
}
Example #2
0
static void InitADFeatures(llvm::Module *M, const char *name,
                          llvm::FunctionType *EPTy) {
  auto FC = M->getOrInsertFunction(name, EPTy);
  auto F = llvm::dyn_cast<llvm::Function>(FC);
  F->setLinkage(llvm::GlobalValue::ExternalLinkage);
  F->addFnAttr(llvm::Attribute::Naked);
}
Example #3
0
static void InitExternalData(NativeModulePtr natMod, llvm::Module *M) {
  for (auto dr : natMod->getExtDataRefs()) {
    auto dsize = dr->getDataSize();
    auto symname = dr->getSymbolName();
    auto extType = llvm::ArrayType::get(llvm::Type::getInt8Ty(M->getContext()),
                                        dsize);
    auto gv = llvm::dyn_cast<llvm::GlobalValue>(
        M->getOrInsertGlobal(symname, extType));
    TASSERT(gv != nullptr, "Could not make global value!");

    if (dr->isWeak()) {
      gv->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
    } else {
      gv->setLinkage(llvm::GlobalValue::ExternalLinkage);
    }

    llvm::Triple triple(M->getTargetTriple());
    if (llvm::Triple::Win32 == triple.getOS()) {
      gv->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
    }
  }
}
Example #4
0
Generator::Generator(llvm::Module *module, llvm::DIScope *debug_scope_)
    : mod(module), debug_scope(debug_scope_) {
  std::map<std::string, llvm::IRBuilder<> **> tors = { { "__ctor", &ctor },
                                                       { "__dtor", &dtor } };
  for (auto &tor : tors) {
    auto func = llvm::cast<llvm::Function>(module->getOrInsertFunction(
        tor.first, llvm::FunctionType::get(
                       llvm::Type::getVoidTy(module->getContext()), false)));
    func->setLinkage(llvm::GlobalValue::InternalLinkage);
    *tor.second = new llvm::IRBuilder<>(
        llvm::BasicBlock::Create(module->getContext(), "entry", func));
  }
}
Example #5
0
void RTTIBuilder::push_void_array(llvm::Constant *CI, Type *valtype,
                                  Dsymbol *mangle_sym) {
  std::string initname(mangle(mangle_sym));
  initname.append(".rtti.voidarr.data");

  const LinkageWithCOMDAT lwc(TYPEINFO_LINKAGE_TYPE, supportsCOMDAT());

  auto G = new LLGlobalVariable(gIR->module, CI->getType(), true,
                                lwc.first, CI, initname);
  setLinkage(lwc, G);
  G->setAlignment(DtoAlignment(valtype));

  push_void_array(getTypeAllocSize(CI->getType()), G);
}
Example #6
0
void RTTIBuilder::push_array(llvm::Constant *CI, uint64_t dim, Type *valtype,
                             Dsymbol *mangle_sym) {
  std::string tmpStr(valtype->arrayOf()->toChars());
  tmpStr.erase(remove(tmpStr.begin(), tmpStr.end(), '['), tmpStr.end());
  tmpStr.erase(remove(tmpStr.begin(), tmpStr.end(), ']'), tmpStr.end());
  tmpStr.append("arr");

  std::string initname(mangle_sym ? mangle(mangle_sym) : ".ldc");
  initname.append(".rtti.");
  initname.append(tmpStr);
  initname.append(".data");

  const LinkageWithCOMDAT lwc(TYPEINFO_LINKAGE_TYPE, supportsCOMDAT());

  auto G = new LLGlobalVariable(gIR->module, CI->getType(), true,
                                lwc.first, CI, initname);
  setLinkage(lwc, G);
  G->setAlignment(DtoAlignment(valtype));

  push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo())));
}
Example #7
0
static void InitLiftedFunctions(NativeModulePtr natMod, llvm::Module *M) {
  for (auto &f : natMod->get_funcs()) {
    NativeFunctionPtr native_func = f.second;
    auto fname = native_func->get_name();
    auto F = M->getFunction(fname);

    if (!F) {
      F = llvm::dyn_cast<llvm::Function>(
          M->getOrInsertFunction(fname, LiftedFunctionType()));

      TASSERT(F != nullptr, "Could not insert function into module");

      ArchSetCallingConv(M, F);
      // make local functions 'static'
      F->setLinkage(llvm::GlobalValue::InternalLinkage);
      std::cout << "Inserted function: " << fname << std::endl;
    } else {
      std::cout << "Already inserted function: " << fname << ", skipping."
                << std::endl;
    }
  }
}
Example #8
0
void RTTIBuilder::finalize(LLType *type, LLValue *value) {
  llvm::ArrayRef<LLConstant *> inits = llvm::makeArrayRef(this->inits);
  LLStructType *st = isaStruct(type);
  assert(st);

  // set struct body
  if (st->isOpaque()) {
    const int n = inits.size();
    std::vector<LLType *> types;
    types.reserve(n);
    for (int i = 0; i < n; ++i) {
      types.push_back(inits[i]->getType());
    }
    st->setBody(types);
  }

  // create the inititalizer
  LLConstant *tiInit = LLConstantStruct::get(st, inits);

  // set the initializer
  llvm::GlobalVariable *gvar = llvm::cast<llvm::GlobalVariable>(value);
  gvar->setInitializer(tiInit);
  setLinkage({TYPEINFO_LINKAGE_TYPE, supportsCOMDAT()}, gvar);
}
Example #9
0
// Iterate over the list of external functions and insert them as
// global functions.
static void InitExternalCode(NativeModulePtr natMod, llvm::Module *M) {
  for (auto e : natMod->getExtCalls()) {
    auto conv = e->getCallingConvention();
    auto argCount = e->getNumArgs();
    auto symName = e->getSymbolName();
    auto funcSign = e->getFunctionSignature();

    // Create the function if it is not already there.
    auto &C = M->getContext();
    auto F = M->getFunction(symName);
    if (F) {
      continue;
    }

    if (ExternalCodeRef::McsemaCall == conv) {
       // normal mcsema function prototypes
      F = llvm::dyn_cast<llvm::Function>(M->getOrInsertFunction(
          ArchNameMcSemaCall(symName), LiftedFunctionType()));
      ArchSetCallingConv(M, F);
      F->setLinkage(llvm::GlobalValue::ExternalLinkage);
      continue;
    }

    std::vector<llvm::Type *> arguments;
    llvm::Type *returnType = nullptr;

    // Create arguments.
    const auto Arch = SystemArch(M);
    const auto OS = SystemOS(M);
    for (auto i = 0; i < argCount; i++) {
      if (_X86_64_ == Arch) {
        if (llvm::Triple::Win32 == OS) {
          if (funcSign.c_str()[i] == 'F') {
            arguments.push_back(llvm::Type::getDoubleTy(C));
          } else {
            arguments.push_back(llvm::Type::getInt64Ty(C));
          }
        } else if (llvm::Triple::Linux == OS) {
          arguments.push_back(llvm::Type::getInt64Ty(C));

        } else {
          TASSERT(false, "Unknown OS Type!");
        }
      } else {
        arguments.push_back(llvm::Type::getInt32Ty(C));
      }
    }

    //create function type
    switch (e->getReturnType()) {
      case ExternalCodeRef::NoReturn:
      case ExternalCodeRef::VoidTy:
        returnType = llvm::Type::getVoidTy(C);
        break;

      case ExternalCodeRef::Unknown:
      case ExternalCodeRef::IntTy:
        if (natMod->is64Bit()) {
          returnType = llvm::Type::getInt64Ty(C);
        } else {
          returnType = llvm::Type::getInt32Ty(C);
        }
        break;

      default:
        throw TErr(
            __LINE__, __FILE__,
            "Encountered an unknown return type while translating function");
    }

    auto FTy = llvm::FunctionType::get(returnType, arguments, false);
    if (e->isWeak()) {
      F = llvm::Function::Create(FTy, llvm::GlobalValue::ExternalWeakLinkage,
                                 symName, M);
    } else {
      F = llvm::Function::Create(FTy, llvm::GlobalValue::ExternalLinkage,
                                 symName, M);
    }

    if (e->getReturnType() == ExternalCodeRef::NoReturn) {
      F->setDoesNotReturn();
    }

    //set calling convention
    if (natMod->is64Bit()) {
      ArchSetCallingConv(M, F);
    } else {
      F->setCallingConv(getLLVMCC(conv));
    }
  }
}
Example #10
0
void setLinkage(Dsymbol *sym, llvm::GlobalObject *obj) {
  setLinkage(DtoLinkage(sym), obj);
}
Example #11
0
llvm::GlobalVariable *genModuleInfo(Module *m) {
  // check declaration in object.d
  const auto moduleInfoType = getModuleInfoType();
  const auto moduleInfoDecl = Module::moduleinfo;

  // The "new-style" ModuleInfo records are variable-length, with the presence
  // of the various fields indicated by a certain flag bit. The base struct
  // should consist only of the _flags/_index fields (the latter of which is
  // unused).
  if (moduleInfoDecl->structsize != 4 + 4) {
    m->error("Unexpected size of struct `object.ModuleInfo`; "
             "druntime version does not match compiler (see -v)");
    fatal();
  }

  // First, figure out which fields are present and set the flags accordingly.
  unsigned flags = MInew;

  const auto fctor = buildModuleCtor(m);
  if (fctor) {
    flags |= MItlsctor;
  }

  const auto fdtor = buildModuleDtor(m);
  if (fdtor) {
    flags |= MItlsdtor;
  }

  const auto fsharedctor = buildModuleSharedCtor(m);
  if (fsharedctor) {
    flags |= MIctor;
  }

  const auto fshareddtor = buildModuleSharedDtor(m);
  if (fshareddtor) {
    flags |= MIdtor;
  }

#if 0
  if (fgetmembers)
    flags |= MIxgetMembers;
#endif

  const auto fictor = getIrModule(m)->coverageCtor;
  if (fictor)
    flags |= MIictor;

  const auto funittest = buildModuleUnittest(m);
  if (funittest) {
    flags |= MIunitTest;
  }

  size_t importedModulesCount;
  const auto importedModules = buildImportedModules(m, importedModulesCount);
  if (importedModules) {
    flags |= MIimportedModules;
  }

  size_t localClassesCount;
  const auto localClasses = buildLocalClasses(m, localClassesCount);
  if (localClasses) {
    flags |= MIlocalClasses;
  }

  if (!m->needmoduleinfo) {
    flags |= MIstandalone;
  }

  // Now, start building the initialiser for the ModuleInfo instance.
  RTTIBuilder b(moduleInfoType);

  b.push_uint(flags);
  b.push_uint(0); // index

  if (fctor) {
    b.push(fctor);
  }
  if (fdtor) {
    b.push(fdtor);
  }
  if (fsharedctor) {
    b.push(fsharedctor);
  }
  if (fshareddtor) {
    b.push(fshareddtor);
  }
#if 0
    if (fgetmembers)
        b.push(fgetmembers);
#endif
  if (fictor) {
    b.push(fictor);
  }
  if (funittest) {
    b.push(funittest);
  }
  if (importedModules) {
    b.push_size(importedModulesCount);
    b.push(importedModules);
  }
  if (localClasses) {
    b.push_size(localClassesCount);
    b.push(localClasses);
  }

  // Put out module name as a 0-terminated string.
  const char *name = m->toPrettyChars();
  const size_t len = strlen(name) + 1;
  const auto it = llvm::IntegerType::getInt8Ty(gIR->context());
  const auto at = llvm::ArrayType::get(it, len);
  b.push(toConstantArray(it, at, name, len, false));

  // Create a global symbol with the above initialiser.
  LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol();
  b.finalize(moduleInfoSym);
  setLinkage({LLGlobalValue::ExternalLinkage, supportsCOMDAT()}, moduleInfoSym);
  return moduleInfoSym;
}