コード例 #1
0
ファイル: irtypeaggr.cpp プロジェクト: John-Colvin/ldc
void AggrTypeBuilder::addAggregate(
    AggregateDeclaration *ad, const AggrTypeBuilder::VarInitMap *explicitInits,
    AggrTypeBuilder::Aliases aliases) {
  const size_t n = ad->fields.dim;
  if (n == 0)
    return;

  // prioritize overlapping fields
  LLSmallVector<FieldPriority, 16> priorities;
  priorities.reserve(n);
  for (auto f : ad->fields) {
    priorities.push_back(prioritize(f, explicitInits));
    IF_LOG Logger::println("Field priority for %s: %d", f->toChars(),
                           priorities.back());
  }

  // mirror the ad->fields array but only fill in contributors
  LLSmallVector<VarDeclaration *, 16> data(n, nullptr);

  // list of pairs: alias => actual field (same offset, same LL type)
  LLSmallVector<std::pair<VarDeclaration *, VarDeclaration *>, 16> aliasPairs;

  // one pass per priority in descending order
  const auto minMaxPriority =
      std::minmax_element(priorities.begin(), priorities.end());
  for (int p = *minMaxPriority.second; p >= *minMaxPriority.first; p--) {
    // iterate over fields of that priority, in declaration order
    for (size_t index = 0; index < n; ++index) {
      if (priorities[index] != p)
        continue;

      VarDeclaration *field = ad->fields[index];
      const size_t f_begin = field->offset;
      const size_t f_end = f_begin + field->type->size();

      // skip empty fields
      if (f_begin == f_end)
        continue;

      // check for overlapping existing fields
      bool overlaps = false;
      if (field->overlapped) {
        for (const auto vd : data) {
          if (!vd)
            continue;

          const size_t v_begin = vd->offset;
          const size_t v_end = v_begin + vd->type->size();

          if (v_begin < f_end && v_end > f_begin) {
            if (aliases == Aliases::AddToVarGEPIndices && v_begin == f_begin &&
                DtoMemType(vd->type) == DtoMemType(field->type)) {
              aliasPairs.push_back(std::make_pair(field, vd));
            }
            overlaps = true;
            break;
          }
        }
      }

      if (!overlaps)
        data[index] = field;
    }
  }

  // Now we can build a list of LLVM types for the actual LL fields.
  // Make sure to zero out any padding and set the GEP indices for the directly
  // indexable variables.

  // first we sort the list by offset
  std::sort(data.begin(), data.end(), var_offset_sort_cb);

  for (const auto vd : data) {
    if (!vd)
      continue;

    assert(vd->offset >= m_offset && "Variable overlaps previous field.");

    // Add an explicit field for any padding so we can zero it, as per TDPL
    // §7.1.1.
    if (m_offset < vd->offset) {
      m_fieldIndex += add_zeros(m_defaultTypes, m_offset, vd->offset);
      m_offset = vd->offset;
    }

    // add default type
    m_defaultTypes.push_back(DtoMemType(vd->type));

    // advance offset to right past this field
    m_offset += getMemberSize(vd->type);

    // set the field index
    m_varGEPIndices[vd] = m_fieldIndex;

    // let any aliases reuse this field/GEP index
    for (const auto &pair : aliasPairs) {
      if (pair.second == vd)
        m_varGEPIndices[pair.first] = m_fieldIndex;
    }

    ++m_fieldIndex;
  }
}
コード例 #2
0
ファイル: naked.cpp プロジェクト: ldc-developers/ldc
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);
}
コード例 #3
0
ファイル: naked.cpp プロジェクト: Safety0ff/ldc
DValue * DtoInlineAsmExpr(Loc loc, FuncDeclaration * fd, Expressions * arguments)
{
    Logger::println("DtoInlineAsmExpr @ %s", loc.toChars());
    LOG_SCOPE;

    TemplateInstance* ti = fd->toParent()->isTemplateInstance();
    assert(ti && "invalid inline __asm expr");

    assert(arguments->dim >= 2 && "invalid __asm call");

    // get code param
    Expression* e = static_cast<Expression*>(arguments->data[0]);
    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(static_cast<char*>(se->string), se->len);

    // get constraints param
    e = static_cast<Expression*>(arguments->data[1]);
    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(static_cast<char*>(se->string), se->len);

    // 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++)
    {
        e = static_cast<Expression*>(arguments->data[i]);
        args.push_back(e->toElem(gIR)->getRVal());
        argtypes.push_back(args.back()->getType());
    }

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

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

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

    // 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");

        TypeStruct* ts = static_cast<TypeStruct*>(type);
        size_t n = ts->sym->fields.dim;
        for (size_t i = 0; i < n; i++)
        {
            llvm::Value* v = gIR->ir->CreateExtractValue(rv, i, "");
            llvm::Value* gep = DtoGEPi(mem, 0, i);
            DtoStore(v, gep);
        }

        return new DVarValue(fd->type->nextOf(), mem);
    }

    // return call as im value
    return new DImValue(fd->type->nextOf(), rv);
}