void ShaderIR::ResolveComponentReference() { // build bidirectional dependency map of component definitions for (auto & comp : Definitions) { comp->Dependency.Clear(); comp->Users.Clear(); } for (auto & comp : Definitions) { List<ShaderComponentSymbol *> workList; for (auto & dep : comp->Implementation->DependentComponents) workList.Add(dep); HashSet<ShaderComponentSymbol*> proceseedDefCompss; for (int i = 0; i < workList.Count(); i++) { auto dep = workList[i]; if (!proceseedDefCompss.Add(dep)) continue; auto & depDefs = DefinitionsByComponent[dep->UniqueName](); // select the best overload according to import operator ordering, // prefer user-pinned definitions (as provided in the choice file) List<String> depWorlds; depWorlds.Add(comp->World); for (auto & w : Shader->Pipeline->WorldDependency[comp->World]()) depWorlds.Add(w); for (int pass = 0; pass < 2; pass++) { // in the first pass, examine the pinned definitions only // in the second pass, examine all the rest definitions for (auto & depWorld : depWorlds) { bool isPinned = false; for (auto existingDef : dep->Type->PinnedWorlds) if (existingDef.StartsWith(depWorld)) { isPinned = true; break; } if (pass == 0 && !isPinned || pass == 1 && isPinned) continue; ComponentDefinitionIR * depDef; if (depDefs.TryGetValue(depWorld, depDef)) { comp->Dependency.Add(depDef); depDef->Users.Add(comp.Ptr()); // add additional dependencies due to import operators if (depWorld != comp->World) { auto importPath = Shader->Pipeline->FindImportOperatorChain(depWorld, comp->World); if (importPath.Count() == 0) throw InvalidProgramException(L"no import path found."); auto & usings = importPath.First().Nodes.Last().ImportOperator->Usings; for (auto & importUsing : usings) { ShaderComponentSymbol* refComp; if (!Shader->AllComponents.TryGetValue(importUsing.Content, refComp)) throw InvalidProgramException(L"import operator dependency not exists."); workList.Add(refComp); } } goto selectionEnd; // first preferred overload is found, terminate searching } } } selectionEnd:; } } }
int VirtualMachine::readProgram(std::istream & input) { qvm_header_t qvminfo; int i, n; uint1_t x[4]; word w; DEBUGTRACE("Loading file...\n"); qvminfo.magic = readInt(input); /* magic. */ if (qvminfo.magic != QVM_MAGIC) { DEBUGTRACE("Invalid magic"); throw InvalidProgramException(); //q3vm_error("Does not appear to be a QVM file."); /* XXX: option to force continue. */ return 0; } DEBUGTRACE("Magic OK\n"); /* variable-length instructions mean instruction count != code length */ qvminfo.inscount = readInt(input); qvminfo.codeoff = readInt(input); qvminfo.codelen = readInt(input); qvminfo.dataoff = readInt(input); qvminfo.datalen = readInt(input); qvminfo.litlen = readInt(input); qvminfo.bsslen = readInt(input); /* Code segment should follow... */ /* XXX: use fseek with SEEK_CUR? */ DEBUGTRACE("Searching for .code @ %d from %d\n", qvminfo.codeoff, input.tellg()); // rom = (q3vm_rom_t*)(hunk); /* ROM-in-hunk */ rom = (Instruction*)calloc(qvminfo.inscount, sizeof(rom[0])); while (input.tellg() < qvminfo.codeoff) readByte(input); while (romSize < qvminfo.inscount) { n = readByte(input); w.int4 = 0; if ((i = opcodeParameterSize(n))) { x[0] = x[1] = x[2] = x[3] = 0; input.readsome((char*)x, i); w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); } rom[romSize].Operation = n; rom[romSize].Parameter = w; romSize++; } DEBUGTRACE("After loading code: at %d, should be %d\n", input.tellg(), qvminfo.codeoff + qvminfo.codelen); /* Then data segment. */ // ram = hunk + ((romlen + 3) & ~3); /* RAM-in-hunk */ ram = hunk; DEBUGTRACE("Searching for .data @ %d from %d\n", qvminfo.dataoff, input.tellg()); while (input.tellg() < qvminfo.dataoff) readByte(input); for (n = 0; n < (qvminfo.datalen / sizeof(uint1_t)); n++) { i = input.readsome((char*)x, sizeof(x)); w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); *((word*)(ram + ramSize)) = w; ramSize += sizeof(word); } /* lit segment follows data segment. */ /* Assembler should have already padded properly. */ DEBUGTRACE("Loading .lit\n"); for (n = 0; n < (qvminfo.litlen / sizeof(uint1_t)); n++) { i = input.readsome((char*)x, sizeof(x)); memcpy(&(w.uint1), &x, sizeof(x)); /* no byte-swapping. */ *((word*)(ram + ramSize)) = w; ramSize += sizeof(word); } /* bss segment. */ DEBUGTRACE("Allocating .bss %d (%X) bytes\n", qvminfo.bsslen, qvminfo.bsslen); /* huge empty chunk. */ ramSize += qvminfo.bsslen; hunkFree = hunkSize - ((ramSize * sizeof(uint1_t)) + 4); DEBUGTRACE("VM hunk has %d of %d bytes free (RAM = %d B).\n", hunkFree, hunkSize, ramSize); if (ramSize > hunkSize) { throw OutOfMemoryException(); return 0; } /* set up stack. */ { int stacksize = 0x10000; dataStack = ramSize - (stacksize / 2); returnStack = ramSize; //returnStack = dataStack+4; RP = returnStack; DP = dataStack; } /* set up PC for return-to-termination. */ PC = romSize + 1; ramMask = ramSize; return 1; }