mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
Compare commits
5 commits
566ad3edd8
...
a70fecb111
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a70fecb111 | ||
|
|
06f86132c3 | ||
|
|
050f8bfe79 | ||
|
|
0f8a3dd1db | ||
|
|
92703954d0 |
|
|
@ -5,6 +5,7 @@ add_library(obj.orbis-kernel OBJECT
|
|||
src/dmem.cpp
|
||||
src/event.cpp
|
||||
src/evf.cpp
|
||||
src/file.cpp
|
||||
src/fmem.cpp
|
||||
src/IoDevice.cpp
|
||||
src/ipmi.cpp
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ struct FileOps {
|
|||
ptr<struct sf_hdtr> hdtr, ptr<off_t> sbytes, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
|
||||
std::string (*toString)(File *file, Thread *thread);
|
||||
std::string (*toString)(File *file);
|
||||
};
|
||||
|
||||
struct File : rx::RcBase {
|
||||
|
|
@ -83,5 +83,6 @@ struct File : rx::RcBase {
|
|||
kvector<Dirent> dirEntries;
|
||||
|
||||
bool noBlock() const { return (flags & 4) != 0; }
|
||||
std::string toString();
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "../ipmi.hpp"
|
||||
#include "../osem.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "rx/StaticString.hpp"
|
||||
#include "types.hpp"
|
||||
#include "ProcessState.hpp"
|
||||
#include "cpuset.hpp"
|
||||
|
|
@ -108,7 +109,7 @@ struct Process final {
|
|||
|
||||
// Named objects for debugging
|
||||
rx::shared_mutex namedObjMutex;
|
||||
kmap<void *, kstring> namedObjNames;
|
||||
kmap<void *, rx::StaticString<32>> namedObjNames;
|
||||
rx::OwningIdMap<NamedObjInfo, uint, 65535, 1> namedObjIds;
|
||||
|
||||
kmap<std::int32_t, SigAction> sigActions;
|
||||
|
|
@ -127,6 +128,7 @@ struct Process final {
|
|||
return ref.get(storage);
|
||||
}
|
||||
|
||||
rx::StaticString<32> getNameOfObject(ptr<const void> addr);
|
||||
Budget *getBudget() const;
|
||||
|
||||
template <typename Cb>
|
||||
|
|
|
|||
13
kernel/orbis/src/file.cpp
Normal file
13
kernel/orbis/src/file.cpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "file.hpp"
|
||||
|
||||
std::string orbis::File::toString() {
|
||||
if (ops && ops->toString) {
|
||||
return ops->toString(this);
|
||||
}
|
||||
|
||||
if (device) {
|
||||
return device->toString();
|
||||
}
|
||||
|
||||
return "<null device>";
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "KernelAllocator.hpp"
|
||||
#include "KernelContext.hpp"
|
||||
#include "rx/format-base.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
|
||||
#include "thread/Process.hpp"
|
||||
|
|
@ -13,11 +14,98 @@
|
|||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
static std::string filterToString(orbis::sshort filter) {
|
||||
switch (filter) {
|
||||
case orbis::kEvFiltRead:
|
||||
return "Read";
|
||||
case orbis::kEvFiltWrite:
|
||||
return "Write";
|
||||
case orbis::kEvFiltAio:
|
||||
return "Aio";
|
||||
case orbis::kEvFiltVnode:
|
||||
return "Vnode";
|
||||
case orbis::kEvFiltProc:
|
||||
return "Proc";
|
||||
case orbis::kEvFiltSignal:
|
||||
return "Signal";
|
||||
case orbis::kEvFiltTimer:
|
||||
return "Timer";
|
||||
case orbis::kEvFiltFs:
|
||||
return "Fs";
|
||||
case orbis::kEvFiltLio:
|
||||
return "Lio";
|
||||
case orbis::kEvFiltUser:
|
||||
return "User";
|
||||
case orbis::kEvFiltPolling:
|
||||
return "Polling";
|
||||
case orbis::kEvFiltDisplay:
|
||||
return "Display";
|
||||
case orbis::kEvFiltGraphicsCore:
|
||||
return "GraphicsCore";
|
||||
case orbis::kEvFiltHrTimer:
|
||||
return "HrTimer";
|
||||
case orbis::kEvFiltUvdTrap:
|
||||
return "UvdTrap";
|
||||
case orbis::kEvFiltVceTrap:
|
||||
return "VceTrap";
|
||||
case orbis::kEvFiltSdmaTrap:
|
||||
return "SdmaTrap";
|
||||
case orbis::kEvFiltRegEv:
|
||||
return "RegEv";
|
||||
case orbis::kEvFiltGpuException:
|
||||
return "GpuException";
|
||||
case orbis::kEvFiltGpuSystemException:
|
||||
return "GpuSystemException";
|
||||
case orbis::kEvFiltGpuDbgGcEv:
|
||||
return "GpuDbgGcEv";
|
||||
}
|
||||
|
||||
return "<invalid " + std::to_string(filter) + ">";
|
||||
}
|
||||
|
||||
static std::string kqueue_toString(orbis::File *file) {
|
||||
auto queue = static_cast<orbis::KQueue *>(file);
|
||||
|
||||
std::string result = "kqueue";
|
||||
|
||||
if (!queue->name.empty()) {
|
||||
result += " \"";
|
||||
result += queue->name;
|
||||
result += "\"";
|
||||
}
|
||||
|
||||
result += " {";
|
||||
|
||||
for (auto ¬e : queue->notes) {
|
||||
result += " knote {";
|
||||
result += filterToString(note.event.filter);
|
||||
|
||||
if (auto file = note.file) {
|
||||
result += " ";
|
||||
result += file->toString();
|
||||
}
|
||||
|
||||
result += rx::format(
|
||||
" ident {:#x}, flags {:#x} fflags {:#x}, data {:#x}, udata {}",
|
||||
note.event.ident, note.event.flags, note.event.fflags, note.event.data,
|
||||
note.event.udata);
|
||||
result += "}";
|
||||
}
|
||||
result += " }";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static orbis::FileOps kqueueOps = {
|
||||
.toString = kqueue_toString,
|
||||
};
|
||||
|
||||
orbis::SysResult orbis::sys_kqueue(Thread *thread) {
|
||||
auto queue = knew<KQueue>();
|
||||
if (queue == nullptr) {
|
||||
return ErrorCode::NOMEM;
|
||||
}
|
||||
queue->ops = &kqueueOps;
|
||||
|
||||
auto fd = thread->tproc->fileDescriptors.insert(queue);
|
||||
ORBIS_LOG_TODO(__FUNCTION__, (int)fd);
|
||||
|
|
@ -36,6 +124,7 @@ orbis::SysResult orbis::sys_kqueueex(Thread *thread, ptr<char> name,
|
|||
if (name != nullptr) {
|
||||
queue->name = name;
|
||||
}
|
||||
queue->ops = &kqueueOps;
|
||||
ORBIS_LOG_TODO(__FUNCTION__, name, flags, (int)fd);
|
||||
thread->retval[0] = std::to_underlying(fd);
|
||||
return {};
|
||||
|
|
|
|||
|
|
@ -158,14 +158,7 @@ struct WrapImpl<Fn> {
|
|||
result += " (";
|
||||
|
||||
if (file) {
|
||||
if (file->ops && file->ops->toString) {
|
||||
result += file->ops->toString(file.get(), thread);
|
||||
} else if (file->device) {
|
||||
result += file->device->toString();
|
||||
} else {
|
||||
result += "<null device>";
|
||||
}
|
||||
|
||||
result += file->toString();
|
||||
} else {
|
||||
result += "<invalid fd>";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,6 +326,15 @@ orbis::Process *orbis::createProcess(Process *parentProcess, pid_t pid) {
|
|||
return &result->object;
|
||||
}
|
||||
|
||||
rx::StaticString<32>
|
||||
orbis::Process::getNameOfObject(ptr<const void> addr) {
|
||||
std::lock_guard lock(namedObjMutex);
|
||||
if (auto it = namedObjNames.find(addr); it != namedObjNames.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::Budget *orbis::Process::getBudget() const {
|
||||
auto result = g_context->budgets.get(budgetId);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,17 +50,17 @@ inline const char *getInstructionName(unsigned id) {
|
|||
case CMP_LE_U32:
|
||||
return "s_cmp_le_u32";
|
||||
case BITCMP0_B32:
|
||||
return "bitcmp0_b32";
|
||||
return "s_bitcmp0_b32";
|
||||
case BITCMP1_B32:
|
||||
return "bitcmp1_b32";
|
||||
return "s_bitcmp1_b32";
|
||||
case BITCMP0_B64:
|
||||
return "bitcmp0_b64";
|
||||
return "s_bitcmp0_b64";
|
||||
case BITCMP1_B64:
|
||||
return "bitcmp1_b64";
|
||||
return "s_bitcmp1_b64";
|
||||
case SETVSKIP:
|
||||
return "setvskip";
|
||||
return "s_setvskip";
|
||||
case ILLEGALD:
|
||||
return "illegald";
|
||||
return "s_illegald";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@
|
|||
#include "ir.hpp"
|
||||
|
||||
namespace shader::transform {
|
||||
ir::Value transformToCanonicalRegion(spv::Context &context,
|
||||
ir::RegionLike region);
|
||||
void transformToCf(spv::Context &context, ir::RegionLike region);
|
||||
void transformToFlat(spv::Context &context, ir::RegionLike region);
|
||||
ir::Value toCanonicalRegion(spv::Context &context, ir::RegionLike region);
|
||||
void toCf(spv::Context &context, ir::RegionLike region);
|
||||
void toFlat(spv::Context &context, ir::RegionLike region);
|
||||
void canonicalizeSwitchSelectionConstructs(spv::Context &context,
|
||||
ir::RegionLike root);
|
||||
} // namespace shader::transform
|
||||
|
|
|
|||
|
|
@ -1,31 +1,27 @@
|
|||
#include "transform.hpp"
|
||||
#include "transform/transformations.hpp"
|
||||
#include "transform/wrap.hpp"
|
||||
#include "SpvConverter.hpp"
|
||||
#include "dialect.hpp"
|
||||
#include <iostream>
|
||||
#include <rx/die.hpp>
|
||||
|
||||
using namespace shader;
|
||||
using namespace shader::transform;
|
||||
|
||||
using Builder = ir::Builder<ir::builtin::Builder, ir::spv::Builder>;
|
||||
|
||||
void shader::structurizeCfg(spv::Context &context, ir::RegionLike region) {
|
||||
// std::cerr << "before transforms: ";
|
||||
// region.print(std::cerr, context.ns);
|
||||
// std::cerr << "\n";
|
||||
|
||||
transformToCanonicalRegion(context, region);
|
||||
transformToCf(context, region);
|
||||
transform::toCanonicalRegion(context, region);
|
||||
transform::toCf(context, region);
|
||||
|
||||
wrapLoopConstructs(context, region);
|
||||
wrapSelectionConstructs(context, region);
|
||||
transform::wrapLoopConstructs(context, region);
|
||||
transform::wrapSelectionConstructs(context, region);
|
||||
transform::canonicalizeSwitchSelectionConstructs(context, region);
|
||||
|
||||
// std::cerr << "structured: ";
|
||||
// region.print(std::cerr, context.ns);
|
||||
// std::cerr << "\n";
|
||||
transformToFlat(context, region);
|
||||
|
||||
transform::toFlat(context, region);
|
||||
|
||||
// std::cerr << "flat: ";
|
||||
// region.print(std::cerr, context.ns);
|
||||
|
|
|
|||
|
|
@ -151,32 +151,6 @@ static std::unordered_map<ir::Value, std::uint32_t> createRouteTerminator(
|
|||
|
||||
successorToId.reserve(toPreds.size());
|
||||
|
||||
auto hasBranchesTo = [](ir::Block from, ir::Block to) {
|
||||
std::vector<ir::Block> workList;
|
||||
std::unordered_set<ir::Block> visited;
|
||||
|
||||
workList.push_back(from);
|
||||
visited.insert(from);
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto block = workList.back();
|
||||
workList.pop_back();
|
||||
|
||||
if (block == to) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto succ : getSuccessors(block)) {
|
||||
if (visited.insert(succ).second) {
|
||||
workList.push_back(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visited.insert(from);
|
||||
return false;
|
||||
};
|
||||
|
||||
for (std::uint32_t id = 0; auto &[succ, pred] : toPreds) {
|
||||
if (id) {
|
||||
routeSwitch.addOperand(id);
|
||||
|
|
@ -184,29 +158,6 @@ static std::unordered_map<ir::Value, std::uint32_t> createRouteTerminator(
|
|||
}
|
||||
successorToId[succ] = id++;
|
||||
}
|
||||
|
||||
auto caseCount = routeSwitch.getOperandCount() / 2 - 1;
|
||||
for (std::size_t i = 1; i < caseCount; ++i) {
|
||||
auto caseValue0 = routeSwitch.getOperand(2 + i * 2);
|
||||
auto caseTarget0 = routeSwitch.getOperand(2 + i * 2 + 1)
|
||||
.getAsValue()
|
||||
.staticCast<ir::Block>();
|
||||
|
||||
for (std::size_t t = 0; t < i; ++t) {
|
||||
auto caseValue1 = routeSwitch.getOperand(2 + t * 2);
|
||||
auto caseTarget1 = routeSwitch.getOperand(2 + t * 2 + 1)
|
||||
.getAsValue()
|
||||
.staticCast<ir::Block>();
|
||||
|
||||
if (hasBranchesTo(caseTarget0, caseTarget1)) {
|
||||
routeSwitch.replaceOperand(2 + i * 2, caseValue1);
|
||||
routeSwitch.replaceOperand(2 + i * 2 + 1, caseTarget1);
|
||||
routeSwitch.replaceOperand(2 + t * 2, caseValue0);
|
||||
routeSwitch.replaceOperand(2 + t * 2 + 1, caseTarget0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return successorToId;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include "SpvConverter.hpp"
|
||||
#include "analyze.hpp"
|
||||
#include "dialect.hpp"
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <rx/die.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
|
@ -13,8 +15,8 @@ using namespace shader::transform;
|
|||
|
||||
using Builder = ir::Builder<ir::builtin::Builder, ir::spv::Builder>;
|
||||
|
||||
ir::Value shader::transform::transformToCanonicalRegion(spv::Context &context,
|
||||
ir::RegionLike region) {
|
||||
ir::Value shader::transform::toCanonicalRegion(spv::Context &context,
|
||||
ir::RegionLike region) {
|
||||
auto cfg = buildCFG(region.getFirst());
|
||||
std::vector<CFG::Node *> exitNodes;
|
||||
for (auto node : cfg.getPreorderNodes()) {
|
||||
|
|
@ -136,9 +138,9 @@ ir::Value shader::transform::transformToCanonicalRegion(spv::Context &context,
|
|||
return newExitBlock;
|
||||
}
|
||||
|
||||
void shader::transform::transformToCf(spv::Context &context,
|
||||
ir::RegionLike region) {
|
||||
void shader::transform::toCf(spv::Context &context, ir::RegionLike region) {
|
||||
ir::Block currentBlock;
|
||||
ir::Block terminationBlock;
|
||||
|
||||
for (auto inst : region.children()) {
|
||||
if (inst == ir::builtin::BLOCK) {
|
||||
|
|
@ -170,13 +172,21 @@ void shader::transform::transformToCf(spv::Context &context,
|
|||
currentBlock.addChild(inst);
|
||||
|
||||
if (isTerminator(inst)) {
|
||||
if (!isBranch(inst)) {
|
||||
terminationBlock = currentBlock;
|
||||
}
|
||||
|
||||
currentBlock = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (terminationBlock != nullptr) {
|
||||
terminationBlock.erase();
|
||||
region.addChild(terminationBlock);
|
||||
}
|
||||
}
|
||||
|
||||
void shader::transform::transformToFlat(spv::Context &context,
|
||||
ir::RegionLike region) {
|
||||
void shader::transform::toFlat(spv::Context &context, ir::RegionLike region) {
|
||||
std::vector<ir::Instruction> workList;
|
||||
|
||||
workList.push_back(region.getFirst());
|
||||
|
|
@ -279,3 +289,116 @@ void shader::transform::transformToFlat(spv::Context &context,
|
|||
insertPoint.eraseAndInsert(inst);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
toCanonicalSwitchSelectionConstruct(spv::Context &context,
|
||||
ir::SelectionConstruct switchConstruct) {
|
||||
auto switchOp = switchConstruct.getHeader().getLast();
|
||||
auto mergeBlock = switchConstruct.getMerge();
|
||||
|
||||
struct CaseInfo {
|
||||
ir::Operand value;
|
||||
ir::Block fallthroughBlock;
|
||||
};
|
||||
|
||||
std::unordered_map<ir::Block, CaseInfo> cases;
|
||||
|
||||
for (std::size_t i = 2; i < switchOp.getOperandCount();) {
|
||||
if (switchOp.getOperand(i + 1) == mergeBlock) {
|
||||
i += 2;
|
||||
} else {
|
||||
auto value = switchOp.eraseOperand(i);
|
||||
auto target = switchOp.eraseOperand(i).getAsValue().cast<ir::Block>();
|
||||
cases[target] = {.value = std::move(value)};
|
||||
}
|
||||
}
|
||||
|
||||
if (cases.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<ir::Block> workList;
|
||||
|
||||
for (auto &[target, caseInfo] : cases) {
|
||||
workList.push_back(target);
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto block = workList.back();
|
||||
workList.pop_back();
|
||||
|
||||
if (block == mergeBlock) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block != target && cases.contains(block)) {
|
||||
caseInfo.fallthroughBlock = block;
|
||||
workList.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto construct = block.cast<ir::Construct>()) {
|
||||
workList.push_back(construct.getMerge());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto succ : getSuccessors(block)) {
|
||||
workList.push_back(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<ir::Block> sortedCases;
|
||||
std::list<std::pair<ir::Block, ir::Block>> workList;
|
||||
|
||||
for (auto &[target, caseInfo] : cases) {
|
||||
if (caseInfo.fallthroughBlock == nullptr) {
|
||||
sortedCases.push_back(target);
|
||||
} else {
|
||||
workList.emplace_back(target, caseInfo.fallthroughBlock);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!sortedCases.empty());
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto [block, fallthroughBlock] = workList.front();
|
||||
workList.pop_front();
|
||||
|
||||
if (auto it = std::ranges::find(sortedCases, fallthroughBlock);
|
||||
it != sortedCases.end()) {
|
||||
sortedCases.insert(it, block);
|
||||
} else {
|
||||
workList.emplace_back(block, fallthroughBlock);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto target : sortedCases) {
|
||||
auto &info = cases.at(target);
|
||||
|
||||
switchOp.addOperand(info.value);
|
||||
switchOp.addOperand(target);
|
||||
}
|
||||
}
|
||||
|
||||
void shader::transform::canonicalizeSwitchSelectionConstructs(
|
||||
spv::Context &context, ir::RegionLike root) {
|
||||
std::vector<ir::Range<ir::Block>> workList;
|
||||
workList.push_back(root.children<ir::Block>());
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto region = workList.back();
|
||||
workList.pop_back();
|
||||
|
||||
for (auto entryBlock : region) {
|
||||
if (auto selection = entryBlock.cast<ir::SelectionConstruct>()) {
|
||||
if (selection.getHeader().getLast() == ir::spv::OpSwitch) {
|
||||
toCanonicalSwitchSelectionConstruct(context, selection);
|
||||
}
|
||||
}
|
||||
|
||||
workList.emplace_back(entryBlock.children<ir::Block>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ orbis::ErrorCode socket_recvfrom(orbis::File *file, void *buf,
|
|||
return orbis::ErrorCode::NOTSUP;
|
||||
}
|
||||
|
||||
static std::string host_toString(orbis::File *file, orbis::Thread *thread) {
|
||||
static std::string host_toString(orbis::File *file) {
|
||||
auto hostFile = static_cast<HostFile *>(file);
|
||||
|
||||
if (!hostFile->path.empty()) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue