Beispiel #1
0
 static void loadImports(llvm::ArrayRef<ImportPtr> imports)
 {
     for (size_t i = 0; i < imports.size(); ++i) {
         module->imports.push_back(imports[i]);
     }
     for (size_t i = 0; i < imports.size(); ++i) {
         loadDependent(module, NULL, imports[i], false);
     }
     for (size_t i = 0; i < imports.size(); ++i) {
         initModule(imports[i]->module);
     }
 }
Beispiel #2
0
static bool matchTempness(CodePtr code,
                          llvm::ArrayRef<ValueTempness> argsTempness,
                          bool callByName,
                          vector<ValueTempness> &tempnessKey,
                          vector<uint8_t> &forwardedRValueFlags)
{
    llvm::ArrayRef<FormalArgPtr> fargs = code->formalArgs;
    
    if (code->hasVarArg)
        assert(fargs.size()-1 <= argsTempness.size());
    else
        assert(fargs.size() == argsTempness.size());

    tempnessKey.clear();
    forwardedRValueFlags.clear();
    
    unsigned varArgSize = argsTempness.size()-fargs.size()+1;
    for (unsigned i = 0, j = 0; i < fargs.size(); ++i) {
        if (callByName && (fargs[i]->tempness == TEMPNESS_FORWARD)) {
                error(fargs[i], "forwarded arguments are not allowed "
                      "in call-by-name procedures");
        }
        if (fargs[i]->varArg) {
            for (; j < varArgSize; ++j) {
                if (!tempnessMatches(argsTempness[i+j], fargs[i]->tempness))
                    return false;
                tempnessKey.push_back(
                    tempnessKeyItem(fargs[i]->tempness,
                                    argsTempness[i+j]));
                bool forwardedRValue =
                    (fargs[i]->tempness == TEMPNESS_FORWARD) &&
                    (argsTempness[i+j] == TEMPNESS_RVALUE);
                forwardedRValueFlags.push_back(forwardedRValue);
            }
            --j;
        } else {
            if (!tempnessMatches(argsTempness[i+j], fargs[i]->tempness))
                return false;
            tempnessKey.push_back(
                tempnessKeyItem(fargs[i]->tempness,
                                argsTempness[i+j]));
            bool forwardedRValue = 
                (fargs[i]->tempness == TEMPNESS_FORWARD) &&
                (argsTempness[i+j] == TEMPNESS_RVALUE);
            forwardedRValueFlags.push_back(forwardedRValue);
        }
    }
    return true;
}
void
PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
{
    const char *data = reinterpret_cast<const char *>(bytes.data());
    PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
    PythonObject::Reset(PyRefType::Owned, py_bytes);
}
Beispiel #4
0
void getProcedureMonoTypes(ProcedureMono &mono, EnvPtr env,
    llvm::ArrayRef<FormalArgPtr> formalArgs, bool hasVarArg)
{
    if (mono.monoState == Procedure_NoOverloads && !hasVarArg)
    {
        assert(mono.monoTypes.empty());
        mono.monoState = Procedure_MonoOverload;
        for (size_t i = 0; i < formalArgs.size(); ++i) {
            if (formalArgs[i]->type == NULL)
                goto poly;
            LocationContext loc(formalArgs[i]->type->location);
            PatternPtr argPattern =
                evaluateOnePattern(formalArgs[i]->type, env);
            ObjectPtr argTypeObj = derefDeep(argPattern);
            if (argTypeObj == NULL)
                goto poly;
            TypePtr argType;
            if (!staticToType(argTypeObj, argType))
                error(formalArgs[i], "expecting a type");

            mono.monoTypes.push_back(argType);
        }
    } else
        goto poly;
    return;

poly:
    mono.monoTypes.clear();
    mono.monoState = Procedure_PolyOverload;
    return;
}
Beispiel #5
0
bool TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) {
  std::stringstream command;
  command << "A";
  for (size_t i = 0; i < inferior_args.size(); i++) {
    if (i > 0)
      command << ',';
    std::string hex_encoded = toHex(inferior_args[i]);
    command << hex_encoded.size() << ',' << i << ',' << hex_encoded;
  }

  if (!SendMessage(command.str()))
    return false;
  if (!SendMessage("qLaunchSuccess"))
    return false;
  std::string response;
  if (!SendMessage("qProcessInfo", response))
    return false;
  auto create_or_error = ProcessInfo::Create(response);
  if (auto create_error = create_or_error.takeError()) {
    GTEST_LOG_(ERROR) << toString(std::move(create_error));
    return false;
  }

  m_process_info = *create_or_error;
  return true;
}
Beispiel #6
0
static void constructCompileCommands(
    CompileCommandPairs &compileCommands,
    const clang::tooling::CompilationDatabase &compilationDatabase,
    llvm::ArrayRef<std::string> sourcePaths)
{
    for (unsigned pathIndex = 0, pathEnd = sourcePaths.size(); pathIndex != pathEnd; pathIndex++)
    {
        llvm::SmallString<1024> filePath(clang::tooling::getAbsolutePath(sourcePaths[pathIndex]));

        std::vector<clang::tooling::CompileCommand> compileCmdsForFile =
            compilationDatabase.getCompileCommands(filePath.str());
        if (!compileCmdsForFile.empty())
        {
            for (int commandsIndex = 0, commandsEnd = compileCmdsForFile.size();
                commandsIndex != commandsEnd; commandsIndex++)
            {
                compileCommands.push_back(
                    std::make_pair(filePath.str(), compileCmdsForFile[commandsIndex]));
            }
        }
        /* - this needs to be collected and the gathered information will be printed eventually
           - not here
        else
        {
            DEBUG({
                llvm::dbgs() << "Skipping " << filePath << ". Command line not found.\n";
            });
        }
        */
    }
}
Beispiel #7
0
void flatten(llvm::ArrayRef<AST_stmt*> roots, std::vector<AST*>& output, bool expand_scopes) {
    FlattenVisitor visitor(&output, expand_scopes);

    for (int i = 0; i < roots.size(); i++) {
        roots[i]->accept(&visitor);
    }
}
Beispiel #8
0
// Minidump string
llvm::Optional<std::string>
lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) {
  std::string result;

  const uint32_t *source_length;
  Status error = consumeObject(data, source_length);
  if (error.Fail() || *source_length > data.size() || *source_length % 2 != 0)
    return llvm::None;

  auto source_start = reinterpret_cast<const llvm::UTF16 *>(data.data());
  // source_length is the length of the string in bytes
  // we need the length of the string in UTF-16 characters/code points (16 bits
  // per char)
  // that's why it's divided by 2
  const auto source_end = source_start + (*source_length) / 2;
  // resize to worst case length
  result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * (*source_length) / 2);
  auto result_start = reinterpret_cast<llvm::UTF8 *>(&result[0]);
  const auto result_end = result_start + result.size();
  llvm::ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end,
                           llvm::strictConversion);
  const auto result_size =
      std::distance(reinterpret_cast<llvm::UTF8 *>(&result[0]), result_start);
  result.resize(result_size); // shrink to actual length

  return result;
}
Beispiel #9
0
void printNameList(llvm::raw_ostream &out, llvm::ArrayRef<ObjectPtr> x)
{
    for (unsigned i = 0; i < x.size(); ++i) {
        if (i != 0)
            out << ", ";
        printName(out, x[i]);
    }
}
Beispiel #10
0
void printNameList(llvm::raw_ostream &out, llvm::ArrayRef<TypePtr> x)
{
    for (size_t i = 0; i < x.size(); ++i) {
        if (i != 0)
            out << ", ";
        printName(out, x[i].ptr());
    }
}
void writeRefs(const SymbolID &ID, llvm::ArrayRef<Ref> Refs,
               const StringTableOut &Strings, llvm::raw_ostream &OS) {
  OS << ID.raw();
  writeVar(Refs.size(), OS);
  for (const auto &Ref : Refs) {
    OS.write(static_cast<unsigned char>(Ref.Kind));
    writeLocation(Ref.Location, Strings, OS);
  }
}
Beispiel #12
0
llvm::ArrayRef<MinidumpThread>
MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) {
  const llvm::support::ulittle32_t *thread_count;
  Status error = consumeObject(data, thread_count);
  if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size())
    return {};

  return llvm::ArrayRef<MinidumpThread>(
      reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count);
}
Beispiel #13
0
void printNameList(llvm::raw_ostream &out, llvm::ArrayRef<ObjectPtr> x, llvm::ArrayRef<unsigned> dispatchIndices)
{
    for (size_t i = 0; i < x.size(); ++i) {
        if (i != 0)
            out << ", ";
        if (find(dispatchIndices.begin(), dispatchIndices.end(), i) != dispatchIndices.end())
            out << "*";
        printName(out, x[i]);
    }
}
Beispiel #14
0
unsigned GenericParamKey::findIndexIn(
                  llvm::ArrayRef<GenericTypeParamType *> genericParams) const {
  // For depth 0, we have random access. We perform the extra checking so that
  // we can return
  if (Depth == 0 && Index < genericParams.size() &&
      genericParams[Index] == *this)
    return Index;

  // At other depths, perform a binary search.
  unsigned result =
      std::lower_bound(genericParams.begin(), genericParams.end(), *this,
                       Ordering())
        - genericParams.begin();
  if (result < genericParams.size() && genericParams[result] == *this)
    return result;

  // We didn't find the parameter we were looking for.
  return genericParams.size();
}
Beispiel #15
0
// Linux Proc Status
// it's stored as an ascii string in the file
llvm::Optional<LinuxProcStatus>
LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) {
  LinuxProcStatus result;
  result.proc_status =
      llvm::StringRef(reinterpret_cast<const char *>(data.data()), data.size());
  data = data.drop_front(data.size());

  llvm::SmallVector<llvm::StringRef, 0> lines;
  result.proc_status.split(lines, '\n', 42);
  // /proc/$pid/status has 41 lines, but why not use 42?
  for (auto line : lines) {
    if (line.consume_front("Pid:")) {
      line = line.trim();
      if (!line.getAsInteger(10, result.pid))
        return result;
    }
  }

  return llvm::None;
}
Beispiel #16
0
llvm::ArrayRef<MinidumpModule>
MinidumpModule::ParseModuleList(llvm::ArrayRef<uint8_t> &data) {

  const llvm::support::ulittle32_t *modules_count;
  Status error = consumeObject(data, modules_count);
  if (error.Fail() || *modules_count * sizeof(MinidumpModule) > data.size())
    return {};

  return llvm::ArrayRef<MinidumpModule>(
      reinterpret_cast<const MinidumpModule *>(data.data()), *modules_count);
}
Beispiel #17
0
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
  if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
    DataExtractor extractor(expr.data(), expr.size(), order_and_width->first,
                            order_and_width->second);
    if (!DWARFExpression::PrintDWARFExpression(s, extractor,
                                               order_and_width->second,
                                               /*dwarf_ref_size*/ 4,
                                               /*location_expression*/ false))
      s.PutCString("invalid-dwarf-expr");
  } else
    s.PutCString("dwarf-expr");
}
Beispiel #18
0
llvm::ArrayRef<MinidumpMemoryDescriptor>
MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
  const llvm::support::ulittle32_t *mem_ranges_count;
  Status error = consumeObject(data, mem_ranges_count);
  if (error.Fail() ||
      *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size())
    return {};

  return llvm::makeArrayRef(
      reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()),
      *mem_ranges_count);
}
Beispiel #19
0
void addGlobals(ModulePtr m, llvm::ArrayRef<TopLevelItemPtr>  toplevels) {
    TopLevelItemPtr const *i, *end;
    for (i = toplevels.begin(), end = toplevels.end();
    i != end; ++i) {
        m->topLevelItems.push_back(*i);
        TopLevelItem *x = i->ptr();
        x->env = m->env;
        switch (x->objKind) {
        case ENUM_DECL : {
                EnumDecl *enumer = (EnumDecl *)x;
                TypePtr t = enumType(enumer);
                addGlobal(m, enumer->name, enumer->visibility, t.ptr());
                for (unsigned i = 0 ; i < enumer->members.size(); ++i) {
                    EnumMember *member = enumer->members[i].ptr();
                    member->index = (int)i;
                    member->type = t;
                    addGlobal(m, member->name, enumer->visibility, member);
                }
                break;
            }
        case PROCEDURE : {
                Procedure *proc = (Procedure *)x;
                if (proc->interface != NULL)
                    proc->interface->env = m->env;
                // fallthrough
            }
        default :
                if (x->name.ptr())
                    addGlobal(m, x->name, x->visibility, x);
        break;
    }

    }

    llvm::ArrayRef<TopLevelItemPtr> items = m->topLevelItems;
    for (size_t i = items.size() - toplevels.size(); i < items.size(); ++i) {
        Object *obj = items[i].ptr();
        switch (obj->objKind) {
        case OVERLOAD :
            initOverload((Overload *)obj);
            break;
        case INSTANCE_DECL :
            initVariantInstance((InstanceDecl *)obj);
            break;
        case STATIC_ASSERT_TOP_LEVEL:
            checkStaticAssert((StaticAssertTopLevel *)obj);
            break;
        default:
            break;
        }
    }

}
Beispiel #20
0
 static void jitTopLevel(llvm::ArrayRef<TopLevelItemPtr> toplevels)
 {
     if (toplevels.empty()) {
         return;
     }
     if (printAST) {
         for (size_t i = 0; i < toplevels.size(); ++i) {
             llvm::errs() << i << ": " << toplevels[i] << "\n";
         }
     }
     addGlobals(module, toplevels);
 }
Beispiel #21
0
  /// \brief Write a block of data, and get the offset that it starts at.
  /// \param Bytes the array of bytes to be written.
  /// \return the offset that this block was written at.
  ///
  offset_uint write(llvm::ArrayRef<char> Bytes) {
    // If the stream doesn't exist, silently ignore the write request.
    if (!Out)
      return noOffset();
    
    auto const Size = Bytes.size();
    Out->write(Bytes.data(), Size);

    // Update the current offset and return the original value.
    auto const WrittenAt = Offset;
    Offset += Size;
    return WrittenAt;
  }
Beispiel #22
0
    static void jitStatements(llvm::ArrayRef<StatementPtr> statements)
    {
        if (statements.empty()) {
            return;
        }

        if (printAST) {
            for (size_t i = 0; i < statements.size(); ++i) {
                llvm::errs() << statements[i] << "\n";
            }
        }

        IdentifierPtr fun = Identifier::get(newFunctionName());

        BlockPtr funBody = new Block(statements);
        ExternalProcedurePtr entryProc =
                new ExternalProcedure(NULL,
                                      fun,
                                      PRIVATE,
                                      vector<ExternalArgPtr>(),
                                      false,
                                      NULL,
                                      funBody.ptr(),
                                      new ExprList());

        entryProc->env = module->env;

        codegenBeforeRepl(module);
        try {
            codegenExternalProcedure(entryProc, true);
        }
        catch (std::exception) {
            return;
        }

        llvm::Function* ctor;
        llvm::Function* dtor;
        codegenAfterRepl(ctor, dtor);

        engine->runFunction(ctor, std::vector<llvm::GenericValue>());

        void* dtorLlvmFun = engine->getPointerToFunction(dtor);
        typedef void (*PFN)();
        atexit((PFN)(uintptr_t)dtorLlvmFun);
        engine->runFunction(entryProc->llvmFunc, std::vector<llvm::GenericValue>());
    }
// Callback invoked when a #pragma warning directive is read.
void PPCallbacksTracker::PragmaWarning(clang::SourceLocation Loc,
                                       llvm::StringRef WarningSpec,
                                       llvm::ArrayRef<int> Ids) {
  beginCallback("PragmaWarning");
  appendArgument("Loc", Loc);
  appendArgument("WarningSpec", WarningSpec);

  std::string Str;
  llvm::raw_string_ostream SS(Str);
  SS << "[";
  for (int i = 0, e = Ids.size(); i != e; ++i) {
    if (i)
      SS << ", ";
    SS << Ids[i];
  }
  SS << "]";
  appendArgument("Ids", SS.str());
}
Beispiel #24
0
static
MatchSuccessPtr findMatchingInvoke(llvm::ArrayRef<OverloadPtr> overloads,
                                   unsigned &overloadIndex,
                                   ObjectPtr callable,
                                   llvm::ArrayRef<TypePtr> argsKey,
                                   MatchFailureError &failures)
{
    while (overloadIndex < overloads.size()) {
        OverloadPtr x = overloads[overloadIndex++];
        MatchResultPtr result = matchInvoke(x, callable, argsKey);
        failures.failures.push_back(make_pair(x, result));
        if (result->matchCode == MATCH_SUCCESS) {
            MatchSuccess *y = (MatchSuccess *)result.ptr();
            return y;
        }
    }
    return NULL;
}
Beispiel #25
0
std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t>
MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) {
  const llvm::support::ulittle64_t *mem_ranges_count;
  Status error = consumeObject(data, mem_ranges_count);
  if (error.Fail() ||
      *mem_ranges_count * sizeof(MinidumpMemoryDescriptor64) > data.size())
    return {};

  const llvm::support::ulittle64_t *base_rva;
  error = consumeObject(data, base_rva);
  if (error.Fail())
    return {};

  return std::make_pair(
      llvm::makeArrayRef(
          reinterpret_cast<const MinidumpMemoryDescriptor64 *>(data.data()),
          *mem_ranges_count),
      *base_rva);
}
Beispiel #26
0
void initializePatternEnv(EnvPtr patternEnv, llvm::ArrayRef<PatternVar> pvars, 
    vector<PatternCellPtr> &cells, vector<MultiPatternCellPtr> &multiCells)
{
    
    for (size_t i = 0; i < pvars.size(); ++i) {
        if (pvars[i].isMulti) {
            MultiPatternCellPtr multiCell = new MultiPatternCell(NULL);
            multiCells.push_back(multiCell);
            cells.push_back(NULL);
            addLocal(patternEnv, pvars[i].name, multiCell.ptr());
        }
        else {
            PatternCellPtr cell = new PatternCell(NULL);
            cells.push_back(cell);
            multiCells.push_back(NULL);
            addLocal(patternEnv, pvars[i].name, cell.ptr());
        }
    }
}
Beispiel #27
0
std::vector<const MinidumpMemoryInfo *>
MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) {
  const MinidumpMemoryInfoListHeader *header;
  Status error = consumeObject(data, header);
  if (error.Fail() ||
      header->size_of_header < sizeof(MinidumpMemoryInfoListHeader) ||
      header->size_of_entry < sizeof(MinidumpMemoryInfo))
    return {};

  data = data.drop_front(header->size_of_header -
                         sizeof(MinidumpMemoryInfoListHeader));

  if (header->size_of_entry * header->num_of_entries > data.size())
    return {};

  std::vector<const MinidumpMemoryInfo *> result;
  for (uint64_t i = 0; i < header->num_of_entries; ++i) {
    result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>(
        data.data() + i * header->size_of_entry));
  }

  return result;
}
Beispiel #28
0
bool
ABISysV_mips::PrepareTrivialCall (Thread &thread,
                                  addr_t sp,
                                  addr_t func_addr,
                                  addr_t return_addr,
                                  llvm::ArrayRef<addr_t> args) const
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (log)
    {
        StreamString s;
        s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
                    thread.GetID(),
                    (uint64_t)sp,
                    (uint64_t)func_addr,
                    (uint64_t)return_addr);

        for (size_t i = 0; i < args.size(); ++i)
            s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
        s.PutCString (")");
        log->PutCString(s.GetString().c_str());
    }

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return false;

    const RegisterInfo *reg_info = NULL;

    RegisterValue reg_value;

    // Argument registers
    const char *reg_names[] = { "r4", "r5", "r6", "r7" };

    llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();

    // Write arguments to registers
    for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i)
    {
        if (ai == ae)
            break;

        reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
        if (log)
            log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);

        if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
            return false;

        ++ai;
    }

    // If we have more than 4 arguments --Spill onto the stack
    if (ai != ae)
    {
        // No of arguments to go on stack 
        size_t num_stack_regs = args.size();

        // Allocate needed space for args on the stack
        sp -= (num_stack_regs * 4);

        // Keep the stack 8 byte aligned
        sp &= ~(8ull-1ull);

        // just using arg1 to get the right size
        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
        
        addr_t arg_pos = sp+16;
        
        size_t i = 4;
        for (; ai != ae; ++ai)
        {
            reg_value.SetUInt32(*ai);
            if (log)
                log->Printf("About to write arg%zd (0x%" PRIx64 ") at  0x%" PRIx64 "", i+1, args[i], arg_pos);
            
            if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail())
                return false;
            arg_pos += reg_info->byte_size;
            i++;
        }
    }

    Error error;
    const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
    const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
    const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);

    if (log)
    log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);

    // Set "sp" to the requested value
    if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
        return false;

    if (log)
    log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);

    // Set "ra" to the return address
    if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr))
        return false;

    if (log)
        log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);

    // Set pc to the address of the called function.
    if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
        return false;

    return true;
}
Beispiel #29
0
void clone(llvm::ArrayRef<CatchPtr> x, vector<CatchPtr> &out)
{
    for (unsigned i = 0; i < x.size(); ++i)
        out.push_back(clone(x[i]));
}
Beispiel #30
0
void clone(llvm::ArrayRef<IdentifierPtr> x, vector<IdentifierPtr> &out)
{
    for (unsigned i = 0; i < x.size(); ++i)
        out.push_back(x[i]);
}