Exemple #1
0
        void visit(PragmaDeclaration *pd)
        {
            if (pd->ident == Id::lib)
            {
                assert(pd->args && pd->args->dim == 1);

                Expression *e = (*pd->args)[0];

                assert(e->op == TOKstring);

                StringExp *se = (StringExp *)e;
                char *name = (char *)mem.xmalloc(se->numberOfCodeUnits() + 1);
                se->writeTo(name, true);

                /* Embed the library names into the object file.
                 * The linker will then automatically
                 * search that library, too.
                 */
                if (!obj_includelib(name))
                {
                    /* The format does not allow embedded library names,
                     * so instead append the library name to the list to be passed
                     * to the linker.
                     */
                    global.params.libfiles->push(name);
                }
            }
            else if (pd->ident == Id::startaddress)
            {
                assert(pd->args && pd->args->dim == 1);
                Expression *e = (*pd->args)[0];
                Dsymbol *sa = getDsymbol(e);
                FuncDeclaration *f = sa->isFuncDeclaration();
                assert(f);
                Symbol *s = toSymbol(f);
                obj_startaddress(s);
            }
            visit((AttribDeclaration *)pd);
        }
Exemple #2
0
  void visit(PragmaDeclaration *decl) override {
    if (decl->ident == Id::lib) {
      assert(decl->args && decl->args->dim == 1);
      assert(!irs->dcomputetarget);
        
      Expression *e = static_cast<Expression *>(decl->args->data[0]);

      assert(e->op == TOKstring);
      StringExp *se = static_cast<StringExp *>(e);
      const std::string name(se->toPtr(), se->numberOfCodeUnits());
      auto nameLen = name.size();

      if (global.params.targetTriple->isWindowsGNUEnvironment()) {
        if (nameLen > 4 && !memcmp(&name[nameLen - 4], ".lib", 4)) {
          // On MinGW, strip the .lib suffix, if any, to improve
          // compatibility with code written for DMD (we pass the name to GCC
          // via -l, just as on Posix).
          nameLen -= 4;
        }

        if (nameLen >= 7 && !memcmp(name.data(), "shell32", 7)) {
          // Another DMD compatibility kludge: Ignore
          // pragma(lib, "shell32.lib"), it is implicitly provided by
          // MinGW.
          return;
        }
      }

      // With LLVM 3.3 or later we can place the library name in the object
      // file. This seems to be supported only on Windows.
      if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
        llvm::SmallString<24> LibName(name);

        // Win32: /DEFAULTLIB:"curl"
        if (LibName.endswith(".a")) {
          LibName = LibName.substr(0, LibName.size() - 2);
        }
        if (LibName.endswith(".lib")) {
          LibName = LibName.substr(0, LibName.size() - 4);
        }
        llvm::SmallString<24> tmp("/DEFAULTLIB:\"");
        tmp.append(LibName);
        tmp.append("\"");
        LibName = tmp;

        // Embed library name as linker option in object file
        auto Value = llvm::MDString::get(gIR->context(), LibName);
        gIR->LinkerMetadataArgs.push_back(
            llvm::MDNode::get(gIR->context(), Value));
      } else {
        size_t const n = nameLen + 3;
        char *arg = static_cast<char *>(mem.xmalloc(n));
        arg[0] = '-';
        arg[1] = 'l';
        memcpy(arg + 2, name.data(), nameLen);
        arg[n - 1] = 0;
        global.params.linkswitches.push(arg);
      }
    }
    visit(static_cast<AttribDeclaration *>(decl));
  }
Exemple #3
0
DValue *DtoInlineAsmExpr(Loc &loc, FuncDeclaration *fd, Expressions *arguments,
                         LLValue *sretPointer) {
  IF_LOG Logger::println("DtoInlineAsmExpr @ %s", loc.toChars());
  LOG_SCOPE;

  assert(fd->toParent()->isTemplateInstance() && "invalid inline __asm expr");
  assert(arguments->dim >= 2 && "invalid __asm call");

  // get code param
  Expression *e = (*arguments)[0];
  IF_LOG Logger::println("code exp: %s", e->toChars());
  StringExp *se = static_cast<StringExp *>(e);
  if (e->op != TOKstring || se->sz != 1) {
    e->error("`__asm` code argument is not a `char[]` string literal");
    fatal();
  }
  std::string code(se->toPtr(), se->numberOfCodeUnits());

  // get constraints param
  e = (*arguments)[1];
  IF_LOG Logger::println("constraint exp: %s", e->toChars());
  se = static_cast<StringExp *>(e);
  if (e->op != TOKstring || se->sz != 1) {
    e->error("`__asm` constraints argument is not a `char[]` string literal");
    fatal();
  }
  std::string constraints(se->toPtr(), se->numberOfCodeUnits());

  // build runtime arguments
  size_t n = arguments->dim;

  LLSmallVector<llvm::Value *, 8> args;
  args.reserve(n - 2);
  std::vector<LLType *> argtypes;
  argtypes.reserve(n - 2);

  for (size_t i = 2; i < n; i++) {
    args.push_back(DtoRVal((*arguments)[i]));
    argtypes.push_back(args.back()->getType());
  }

  // build asm function type
  Type *type = fd->type->nextOf();
  LLType *ret_type = DtoType(type->toBasetype());
  llvm::FunctionType *FT = llvm::FunctionType::get(ret_type, argtypes, false);

  // make sure the constraints are valid
  if (!llvm::InlineAsm::Verify(FT, constraints)) {
    e->error("`__asm` constraint argument is invalid");
    fatal();
  }

  // build asm call
  bool sideeffect = true;
  llvm::InlineAsm *ia = llvm::InlineAsm::get(FT, code, constraints, sideeffect);

  llvm::Value *rv = gIR->ir->CreateCall(ia, args, "");

  if (sretPointer) {
    DtoStore(rv, DtoBitCast(sretPointer, getPtrToType(ret_type)));
    return new DLValue(type, sretPointer);
  }

  // work around missing tuple support for users of the return value
  if (type->ty == Tstruct) {
    // make a copy
    llvm::Value *mem = DtoAlloca(type, ".__asm_tuple_ret");
    DtoStore(rv, DtoBitCast(mem, getPtrToType(ret_type)));
    return new DLValue(type, mem);
  }

  // return call as im value
  return new DImValue(type, rv);
}