Value InterpretedVM::TextureSample(Value sampler, Value coord, Value bias, uint32 resultTypeId) {
  STypeSampler* samplerType =(STypeSampler*)GetType(sampler.TypeId).Memory;
  assert(samplerType->Content == 2);
  assert(ElementCount(coord.TypeId) >= samplerType->Dim + samplerType->Arrayed);
  Sampler* s = ((Sampler*)sampler.Memory);
  uint32 index = 0;
  uint32 acc = 1;
  for (int d = 0; d < s->DimCount; d++) {
    uint32 dd = s->Dims[d];
    uint32 add = (uint32)(*(float*)IndexMemberValue(coord, d).Memory * (dd - 1) + 0.5f);
    switch (s->WrapMode) {
    case WrapMode::WMClamp: add = add < 0 ? 0 : add > dd - 1 ? dd - 1 : add; break;
    case WrapMode::WMRepeat: add = add % dd; break;
    }
    index += add * acc;
    acc *= dd;
  }
  return VmInit(resultTypeId, ((float*)s->Data) + index * 4);
}
Example #2
0
int
start5(char *arg)
{
    int  pid;
    int  status;

    Tconsole("start5(): Running %s\n", TEST);
    Tconsole("start5(): Pagers: %d, Mappings : %d, Pages: %d, Frames: %d, Children %d, Iterations %d, Priority %d.\n", PAGERS, MAPPINGS, PAGES, FRAMES, CHILDREN, ITERATIONS, PRIORITY);

    vmRegion = VmInit( MAPPINGS, PAGES, FRAMES, PAGERS );

    Spawn("Child", Child,  0,USLOSS_MIN_STACK*7,PRIORITY, &pid);
    SemP( sem);
    Wait(&pid, &status);
    verify(status == 117);

    Tconsole("start5 done\n");
    //PrintStats();
    VmDestroy();
    Terminate(1);

    return 0;
} /* start5 */
Example #3
0
int
start5(char *arg)
{
    int  pid;
    int  status;

    Tconsole("start5(): Running:    %s\n", TEST);
    Tconsole("start5(): Pagers:     %d\n", PAGERS);
    Tconsole("          Mappings:   %d\n", MAPPINGS);
    Tconsole("          Pages:      %d\n", PAGES);
    Tconsole("          Frames:     %d\n", FRAMES);
    Tconsole("          Children:   %d\n", CHILDREN);
    Tconsole("          Iterations: %d\n", ITERATIONS);
    Tconsole("          Priority:   %d\n", PRIORITY);

    status = VmInit( MAPPINGS, PAGES, FRAMES, PAGERS, &vmRegion );
    Tconsole("start5(): after call to VmInit, status = %d\n\n", status);
    assert(status == 0);
    assert(vmRegion != NULL);

    SemCreate(0, &sem);

    Spawn("Child", Child, NULL, USLOSS_MIN_STACK * 7, PRIORITY, &pid);

    SemP( sem);

    Wait(&pid, &status);
    assert(status == 117);

    Tconsole("start5(): done\n");
    //PrintStats();
    VmDestroy();
    Terminate(1);

    return 0;
} /* start5 */
uint32 InterpretedVM::Execute(Function* func) {
  prog.CurrentFunction = func;

  int pc = 0;

  for (;;) {
    auto op = func->Ops[pc];
    switch (op.Op) {
    case Op::OpBranch: {
      auto branch = (SBranch*)op.Memory;
      pc = func->Labels.at(branch->TargetLabelId);
      break;
    }
    case Op::OpBranchConditional: {
      auto branch = (SBranchConditional*)op.Memory;
      uint32 labelID;
      Value val = Dereference(env.Values[branch->ConditionId]);
      if (*(bool*)val.Memory) {
        labelID = branch->TrueLabelId;
      } else {
        labelID = branch->FalseLabelId;
      }
      pc = func->Labels.at(labelID);
      break;
    }
    case Op::OpFunctionCall: {
      auto call = (SFunctionCall*)op.Memory;
      Function toCall = prog.FunctionDefinitions.at(call->FunctionId);
      for (int i = 0; i < call->ArgumentIdsCount; i++) {
        env.Values[toCall.Parameters[i].ResultId] = Dereference(env.Values.at(call->ArgumentIds[i]));
      }
      uint32 resultId = Execute(&toCall);
      if (resultId == -1) {
        return -1;
      }
      prog.CurrentFunction = func;
      env.Values[call->ResultId] = env.Values[resultId];
      break;
    }
    case Op::OpExtInst: {
      auto extInst = (SExtInst*)op.Memory;
      Value* ops = new Value[extInst->OperandIdsCount];
      for (int i = 0; i < extInst->OperandIdsCount; i++) {
        ops[i] = Dereference(env.Values.at(extInst->OperandIds[i]));
      }

      ExtInstFunc* func = env.Extensions[extInst->SetId][extInst->Instruction];
      env.Values[extInst->ResultId] = func(this, extInst->ResultTypeId, extInst->OperandIdsCount, ops);
      break;
    }
    case Op::OpConvertSToF: {
      auto convert = (SConvertSToF*)op.Memory;
      Value op1 = Dereference(env.Values[convert->SignedValueId]);
      env.Values[convert->ResultId] = DoOp(convert->ResultTypeId, Convert<int32, float>, op1);
      break;
    }
    case Op::OpFAdd: {
      auto add = (SFAdd*)op.Memory;
      Value op1 = Dereference(env.Values[add->Operand1Id]);
      Value op2 = Dereference(env.Values[add->Operand2Id]);
      env.Values[add->ResultId] = DoOp(add->ResultTypeId, Add<float>, op1, op2);
      break;
    }
    case Op::OpIAdd: {
      auto add = (SIAdd*)op.Memory;
      Value op1 = Dereference(env.Values[add->Operand1Id]);
      Value op2 = Dereference(env.Values[add->Operand2Id]);
      env.Values[add->ResultId] = DoOp(add->ResultTypeId, Add<int>, op1, op2);
      break;
    }
    case Op::OpFSub: {
      auto sub = (SFSub*)op.Memory;
      Value op1 = Dereference(env.Values[sub->Operand1Id]);
      Value op2 = Dereference(env.Values[sub->Operand2Id]);
      env.Values[sub->ResultId] = DoOp(sub->ResultTypeId, Sub<float>, op1, op2);
      break;
    }
    case Op::OpISub: {
      auto sub = (SISub*)op.Memory;
      Value op1 = Dereference(env.Values[sub->Operand1Id]);
      Value op2 = Dereference(env.Values[sub->Operand2Id]);
      env.Values[sub->ResultId] = DoOp(sub->ResultTypeId, Sub<int>, op1, op2);
      break;
    }
    case Op::OpFDiv: {
      auto div = (SFDiv*)op.Memory;
      Value op1 = Dereference(env.Values[div->Operand1Id]);
      Value op2 = Dereference(env.Values[div->Operand2Id]);
      env.Values[div->ResultId] = DoOp(div->ResultTypeId, Div<float>, op1, op2);
      break;
    }
    case Op::OpFMul: {
      auto mul = (SFMul*)op.Memory;
      Value op1 = Dereference(env.Values[mul->Operand1Id]);
      Value op2 = Dereference(env.Values[mul->Operand2Id]);
      env.Values[mul->ResultId] = DoOp(mul->ResultTypeId, Mul<float>, op1, op2);
      break;
    }
    case Op::OpIMul: {
      auto mul = (SFMul*)op.Memory;
      Value op1 = Dereference(env.Values[mul->Operand1Id]);
      Value op2 = Dereference(env.Values[mul->Operand2Id]);
      env.Values[mul->ResultId] = DoOp(mul->ResultTypeId, Mul<int>, op1, op2);
      break;
    }
    case Op::OpVectorTimesScalar: {
      auto vts = (SVectorTimesScalar*)op.Memory;
      Value scalar = Dereference(env.Values[vts->ScalarId]);
      Value vector = Dereference(env.Values[vts->VectorId]);
      env.Values[vts->ResultId] = DoOp(vts->ResultTypeId, [scalar](Value comp) {return Mul<float>(scalar, comp);}, vector);
      break;
    }
    case Op::OpSLessThan: {
      auto lessThan = (SSLessThan*)op.Memory;
      Value op1 = Dereference(env.Values[lessThan->Operand1Id]);
      Value op2 = Dereference(env.Values[lessThan->Operand2Id]);
      env.Values[lessThan->ResultId] = DoOp(lessThan->ResultTypeId, [](Value a, Value b) { return Cmp<int32>(a, b) == -1; }, op1, op2);
      break;
    }
    case Op::OpSGreaterThan: {
      auto greaterThan = (SSLessThan*)op.Memory;
      Value op1 = Dereference(env.Values[greaterThan->Operand1Id]);
      Value op2 = Dereference(env.Values[greaterThan->Operand2Id]);
      env.Values[greaterThan->ResultId] = DoOp(greaterThan->ResultTypeId, [](Value a, Value b) { return Cmp<int32>(a, b) == 1; }, op1, op2);
      break;
    }
    case Op::OpLoad: {
      auto load = (SLoad*)op.Memory;
      auto valueToLoad = env.Values.at(load->PointerId);
      env.Values[load->ResultId] = valueToLoad;
      break;
    }
    case Op::OpStore: {
      auto store = (SStore*)op.Memory;
      auto val = env.Values[store->ObjectId];
      auto var = GetType(val.TypeId);
      if (var.Op == Op::OpTypePointer) {
        SetVariable(store->PointerId, val.Memory);
      } else {
        SetVariable(store->PointerId, &val.Memory);
      }
      break;
    }
    case Op::OpTextureSample: {
      auto sample = (STextureSample*)op.Memory;
      auto sampler = Dereference(env.Values.at(sample->SamplerId));
      auto coord = Dereference(env.Values.at(sample->CoordinateId));
      Value bias = { 0, 0 };
      if (sample->BiasId != 0) {
        bias = Dereference(env.Values.at(sample->BiasId));
      }

      env.Values[sample->ResultId] = TextureSample(sampler, coord, bias, sample->ResultTypeId);
      break;
    }
    case Op::OpLabel:
    case Op::OpSelectionMerge:
    case Op::OpLoopMerge:
      break;
    case Op::OpAccessChain: {
      auto access = (SAccessChain*)op.Memory;
      auto val = Dereference(env.Values.at(access->BaseId));

      uint32* indices = new uint32[access->IndexesIdsCount];
      for (int i = 0; i < access->IndexesIdsCount; i++) {
        indices[i] = *(uint32*)Dereference(env.Values[access->IndexesIds[i]]).Memory;
      }

      byte* mem = GetPointerInComposite(val.TypeId, val.Memory, access->IndexesIdsCount, indices);
      delete indices;

      Value res = VmInit(access->ResultTypeId, &mem);
      env.Values[access->ResultId] = res;
      break;
    }
    case Op::OpVectorShuffle: {
      auto vecShuffle = (SVectorShuffle*)op.Memory;
      auto vec1 = Dereference(env.Values.at(vecShuffle->Vector1Id));
      auto vec2 = Dereference(env.Values.at(vecShuffle->Vector2Id));

      auto result = VmInit(vecShuffle->ResultTypeId, nullptr);
      int v1ElCount = ElementCount(vec1.TypeId);
      for (int i = 0; i < vecShuffle->ComponentsCount; i++) {
        int index = vecShuffle->Components[i];
        Value toCopy;
        if (index < v1ElCount) {
          toCopy = vec1;
        } else {
          index -= v1ElCount;
          toCopy = vec2;
        }

        Value elToCopy = IndexMemberValue(toCopy, index);
        memcpy(IndexMemberValue(result, i).Memory, elToCopy.Memory, GetTypeByteSize(elToCopy.TypeId));
      }

      env.Values[vecShuffle->ResultId] = result;
      break;
    }
    //TODO: FIX INDICES (NOT HIERARCHY!)
    case Op::OpCompositeExtract: {
      auto extract = (SCompositeExtract*)op.Memory;
      auto composite = env.Values[extract->CompositeId];
      byte* mem = GetPointerInComposite(composite.TypeId, composite.Memory, extract->IndexesCount, extract->Indexes);
      Value val = { extract->ResultTypeId, VmAlloc(extract->ResultTypeId) };
      memcpy(val.Memory, mem, GetTypeByteSize(val.TypeId));
      env.Values[extract->ResultId] = val;
      break;
    }
    case Op::OpCompositeInsert: {
      auto insert = (SCompositeInsert*)op.Memory;
      auto composite = Dereference(env.Values[insert->CompositeId]);
      Value val = Dereference(env.Values.at(insert->ObjectId));
      byte* mem = GetPointerInComposite(composite.TypeId, composite.Memory, insert->IndexesCount, insert->Indexes);
      memcpy(mem, val.Memory, GetTypeByteSize(val.TypeId));
      env.Values[insert->ResultId] = VmInit(composite.TypeId, composite.Memory);
      break;
    }
    case Op::OpCompositeConstruct: {
      auto construct = (SCompositeConstruct*)op.Memory;
      Value val = { construct->ResultTypeId, VmAlloc(construct->ResultTypeId) };
      env.Values[construct->ResultId] = val;
      byte* memPtr = val.Memory;
      for (int i = 0; i < construct->ConstituentsIdsCount; i++) {
        auto memVal = env.Values[construct->ConstituentsIds[i]];
        uint32 memSize = GetTypeByteSize(memVal.TypeId);
        memcpy(memPtr, memVal.Memory, memSize);
        memPtr += memSize;
      }
      assert(memPtr - val.Memory == GetTypeByteSize(construct->ResultTypeId));
      break;
    }
    case Op::OpVariable: {
      auto var = (SVariable*)op.Memory;
      Value val = { var->ResultTypeId, VmAlloc(var->ResultTypeId) };
      if (var->InitializerId) {
        memcpy(val.Memory, env.Values[var->InitializerId].Memory, GetTypeByteSize(val.TypeId));
      }
      else {
        memset(val.Memory, 0, GetTypeByteSize(val.TypeId));
      }
      env.Values[var->ResultId] = val;
      break;
    }
    case Op::OpReturnValue: {
      auto ret = (SReturnValue*)op.Memory;
      return ret->ValueId;
    }
    case Op::OpReturn:
      return 0;
    default:
      std::cout << "Unimplemented operation: " << writeOp(op);
      return -1;
    }

    pc++;
  }
  return 0;
}