Пример #1
0
		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;
	}