Value* Builder::getConstantV256(V256 c) { Value* value = allocValue(TYPE_V256); value->setConstantV256(c); return value; }
void parseSpell(Game& game, const Value& elem) { auto level = game.Resources().getLevel(getStringKey(elem, "level")); if (level == nullptr) { return; } std::string id; auto spell = parseSpellHelper(game, *level, elem, id); if (spell == nullptr) { return; } spell->Id(id); if (elem.HasMember("name") == true) { spell->Name(getStringVal(elem["name"])); } if (elem.HasMember("type") == true) { spell->SpellType(getStringVal(elem["type"])); } if (elem.HasMember("properties") == true) { const auto& props = elem["properties"]; if (props.IsObject() == true) { for (auto it = props.MemberBegin(); it != props.MemberEnd(); ++it) { if (it->name.GetStringLength() > 0) { auto name = getStringViewVal(it->name); auto nameHash = str2int16(name); level->setPropertyName(nameHash, name); spell->setIntByHash(nameHash, getMinMaxIntVal<LevelObjValue>(it->value)); } } } } if (elem.HasMember("descriptions") == true) { const auto& descriptions = elem["descriptions"]; if (descriptions.IsObject() == true) { parseDescriptionValue(*spell, *level, descriptions); } else if (descriptions.IsArray() == true) { for (const auto& val : descriptions) { parseDescriptionValue(*spell, *level, val); } } } if (elem.HasMember("formulas") == true) { const auto& formulas = elem["formulas"]; if (formulas.IsObject() == true) { for (auto it = formulas.MemberBegin(); it != formulas.MemberEnd(); ++it) { auto nameHash = str2int16(getStringViewVal(it->name)); if (nameHash != str2int16("")) { spell->setFormula(nameHash, getStringVal(it->value)); } } } } level->addClass(id, std::move(spell)); }
Value * CallGen::generateCode(const Generater& generater) { auto* m = generater.module; auto func = generater.func; auto& builder = generater.builder(); if (!llvmFunction) { if (pointerGen) { // 函数指针 Value* v = pointerGen->generate(generater); auto *x=dyn_cast<PointerType>(v->getType()); if (x->getElementType()->isPointerTy()) { // 函数是作为指针保存的 Type* t = PointerType::get(pointerGen->type, 0); // v = builder.CreateBitOrPointerCast(v, t); llvmFunction = builder.CreateLoad(v); } else { llvmFunction = v; } } else { assert(function); llvmFunction = function->generateCode(m, builder.getContext()); funcType = function->func->getFunctionType(); } } if(function) function->generateBody(m, builder.getContext()); auto iter = funcType->param_begin(); auto end = funcType->param_end(); std::vector< llvm::Value* > a; if (object) putBack(builder, a, object->generate(generater), iter, end); for (auto *i : params) { Value* v = i->generate(generater); // 如果是基本类型 if (i->type->isIntegerTy() || i->type->isFloatingPointTy()) { if (v->getType()->isPointerTy()) v = builder.CreateLoad(v); putBack(builder, a, v, iter, end); } else if (i->type->isArrayTy()) { putBack(builder, a, v, iter, end); // 写入大小 auto sz = i->type->getArrayNumElements(); auto* s = ConstantInt::get(func->getContext(), APInt(32, sz)); putBack(builder, a, s, iter, end); } else { putBack(builder, a, v, iter, end); } } std::clog << "Call func " << llvmFunction->getName().str() << std::endl; Value* v= builder.CreateCall(funcType, llvmFunction, a); // 添加一个强制转换,避免某些 c 函数返回的类型不一致 if (type->isStructTy()) { Type* ty = llvm::PointerType::get(type, 0); return builder.CreateBitOrPointerCast(v, ty); } return v; }
void JSONValue::AddBool(bool value) { Value jsonValue; jsonValue.SetBool(value); AddMember(jsonValue); }
void JSONValue::AddString(const String& value) { Value jsonValue; jsonValue.SetString(value.CString(), value.Length(), file_->GetDocument()->GetAllocator()); AddMember(jsonValue); }
void JSONValue::SetInt(const String& name, int value) { Value jsonValue; jsonValue.SetInt(value); AddMember(name, jsonValue); }
void JSONValue::SetFloat(const String& name, float value) { Value jsonValue; jsonValue.SetDouble((double)value); AddMember(name, jsonValue); }
Value* Builder::getConstantV128(V128 c) { Value* value = allocValue(TYPE_V128); value->setConstantV128(c); return value; }
ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const { ValueObjectSP return_valobj_sp; Value value; ExecutionContext exe_ctx (thread.shared_from_this()); if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; value.SetClangType(return_clang_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; const size_t byte_size = return_clang_type.GetByteSize(nullptr); const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); bool success = false; if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers // In MIPS register "r2" (v0) holds the integer function return values uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) { default: break; case sizeof(uint64_t): if (is_signed) value.GetScalar() = (int64_t)(raw_value); else value.GetScalar() = (uint64_t)(raw_value); success = true; break; case sizeof(uint32_t): if (is_signed) value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); else value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); success = true; break; case sizeof(uint16_t): if (is_signed) value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); else value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); success = true; break; case sizeof(uint8_t): if (is_signed) value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); else value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); success = true; break; } } if (success) return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsPointer) { value.SetValueType(Value::eValueTypeScalar); uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); value.GetScalar() = (uint64_t)(raw_value); return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { // TODO: Handle vector types } return return_valobj_sp; }
Value* Builder::getConstantF32(F32 c) { Value* value = allocValue(TYPE_F32); value->setConstantF32(c); return value; }
Value* Builder::getConstantF64(F64 c) { Value* value = allocValue(TYPE_F64); value->setConstantF64(c); return value; }
Value* Builder::getConstantI16(U16 c) { Value* value = allocValue(TYPE_I16); value->setConstantI16(c); return value; }
// HIR constants Value* Builder::getConstantI8(U8 c) { Value* value = allocValue(TYPE_I8); value->setConstantI8(c); return value; }
Value* Builder::getConstantPointer(void* c) { Value* value = allocValue(TYPE_PTR); value->setConstantI64(reinterpret_cast<U64>(c)); return value; }
bool CallAnalyzer::visitCmpInst(CmpInst &I) { Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); // First try to handle simplified comparisons. if (!isa<Constant>(LHS)) if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS)) LHS = SimpleLHS; if (!isa<Constant>(RHS)) if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS)) RHS = SimpleRHS; if (Constant *CLHS = dyn_cast<Constant>(LHS)) { if (Constant *CRHS = dyn_cast<Constant>(RHS)) if (Constant *C = ConstantExpr::getCompare(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; return true; } } if (I.getOpcode() == Instruction::FCmp) return false; // Otherwise look for a comparison between constant offset pointers with // a common base. Value *LHSBase, *RHSBase; APInt LHSOffset, RHSOffset; llvm::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); if (LHSBase) { llvm::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); if (RHSBase && LHSBase == RHSBase) { // We have common bases, fold the icmp to a constant based on the // offsets. Constant *CLHS = ConstantInt::get(LHS->getContext(), LHSOffset); Constant *CRHS = ConstantInt::get(RHS->getContext(), RHSOffset); if (Constant *C = ConstantExpr::getICmp(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; ++NumConstantPtrCmps; return true; } } } // If the comparison is an equality comparison with null, we can simplify it // for any alloca-derived argument. if (I.isEquality() && isa<ConstantPointerNull>(I.getOperand(1))) if (isAllocaDerivedArg(I.getOperand(0))) { // We can actually predict the result of comparisons between an // alloca-derived value and null. Note that this fires regardless of // SROA firing. bool IsNotEqual = I.getPredicate() == CmpInst::ICMP_NE; SimplifiedValues[&I] = IsNotEqual ? ConstantInt::getTrue(I.getType()) : ConstantInt::getFalse(I.getType()); return true; } // Finally check for SROA candidates in comparisons. Value *SROAArg; DenseMap<Value *, int>::iterator CostIt; if (lookupSROAArgAndCost(I.getOperand(0), SROAArg, CostIt)) { if (isa<ConstantPointerNull>(I.getOperand(1))) { accumulateSROACost(CostIt, InlineConstants::InstrCost); return true; } disableSROA(CostIt); } return false; }
int main(int argc, char *argv[]) { // usual stuff... Network yarp; if (!yarp.checkNetwork()) { printf("YARP is not available!\n"); return 1; } ResourceFinder rf; rf.configure(argc,argv); string name=rf.check("name",Value("tuner")).asString(); string robot=rf.check("robot",Value("icub")).asString(); string part=rf.check("part",Value("right_arm")).asString(); int joint=rf.check("joint",Value(11)).asInt(); double encoder=rf.check("encoder",Value(2.43)).asDouble(); Property pOptions; pOptions.put("device","remote_controlboard"); pOptions.put("remote","/"+robot+"/"+part); pOptions.put("local","/"+name+"/"+part); PolyDriver driver(pOptions); if (!driver.isValid()) { printf("Part \"%s\" is not ready!\n",string("/"+robot+"/"+part).c_str()); return 1; } // ##### Preamble // The objective is to tune online a P controller that will make // the joint move complying with some given bandwidth specification. // // The plant is to be identified using an Extended-Kalman-Filter (EKF) // under the assumption that the adopted model obeys to the following // tansfer function which gives out the position when fed with voltage: // // K / (s*(1 + tau*s)) // // You might have realized that we disregard the electrical dynamics in // favour of the slower mechanical one represented by the time constant tau. // // ##### Additional notes on the control design // The low-level layer provides the user with a PID controller. However, the // I part is not specifically required for such control task since by virtue // of the internal model principle the steady-state error can be already // compensated thanks to the presence of the integrator in the plant. On the // other hand, this principle holds only for linear systems and indeed, // nonlinear effects - such as the stiction - make the final behavior deviate // from this baseline, eventually requiring the integral part. Nonetheless, // if stiction is compensated separately, I is again not strictly needed. // // Finally, a few words about the D part. In order to include D within the design, // the derivative part must be implemented according to the standard which states // that D = Kd*s / (1 + tau_d*s). // // In the following a short example will guide you through the steps required // to identify the plant, validate the retrieved model and then design the // P controller that meets the user specifications. Stiction identification is // carried out as well. // First thing to do is to prepare configuration options // which are to be given in the form: // // [general] // joint ... // port ... // [plant_estimation] // Ts ... // ... // [stiction_estimation] // ... Property pGeneral; pGeneral.put("joint",joint); // the "port" option allows opening up a yarp port which // will stream out useful information while identifying // and validating the system pGeneral.put("port","/"+name+"/info:o"); string sGeneral="(general "; sGeneral+=pGeneral.toString(); sGeneral+=')'; Bottle bGeneral,bPlantEstimation,bStictionEstimation; bGeneral.fromString(sGeneral); // here follow the parameters for the EKF along with the // initial values for tau and K bPlantEstimation.fromString("(plant_estimation (Ts 0.01) (Q 1.0) (R 1.0) (P0 100000.0) (tau 1.0) (K 1.0) (max_pwm 800.0))"); bStictionEstimation.fromString("(stiction_estimation (Ts 0.01) (T 2.0) (vel_thres 5.0) (e_thres 1.0) (gamma (10.0 10.0)) (stiction (0.0 0.0)))"); // compose the overall configuration Bottle bConf=bGeneral; bConf.append(bPlantEstimation); bConf.append(bStictionEstimation); pOptions.fromString(bConf.toString()); OnlineCompensatorDesign designer; if (!designer.configure(driver,pOptions)) { printf("Configuration failed!\n"); return 1; } // let's start the plant estimation by // setting up an experiment that will // last 20 seconds // // the experiment foresees a direct control // in voltage (pwm) Property pPlantEstimation; pPlantEstimation.put("max_time",20.0); // the switch_timeout option enforces a timeout // in the voltage switching logic to produce // rising and falling transitions. pPlantEstimation.put("switch_timeout",2.0); designer.startPlantEstimation(pPlantEstimation); printf("Estimation experiment will last %g seconds...\n", pPlantEstimation.find("max_time").asDouble()); double t0=Time::now(); while (!designer.isDone()) { printf("elapsed %d [s]\n",(int)(Time::now()-t0)); Time::delay(1.0); } // retrieve the identified values (averaged over time) Property pResults; designer.getResults(pResults); double tau=pResults.find("tau_mean").asDouble(); double K=pResults.find("K_mean").asDouble(); printf("plant = K/s * 1/(1+s*tau)\n"); printf("Estimated parameters...\n"); printf("tau = %g\n",tau); printf("K = %g\n",K); // put the model to test for 10 seconds by // simulating the plant with a Kalman filter Property pPlantValidation; pPlantValidation.put("max_time",10.0); pPlantValidation.put("switch_timeout",2.0); pPlantValidation.put("tau",tau); pPlantValidation.put("K",K); // the "measure_update_ticks" option tells that // the measurement update will occur 100 times slower // with respect to the sample time. This way we give // the model enough time to evolve to test its properties // before comparing its response with the real output // to counteract drift phenomena. pPlantValidation.put("measure_update_ticks",100); designer.startPlantValidation(pPlantValidation); printf("Validation experiment will last %g seconds...\n", pPlantValidation.find("max_time").asDouble()); t0=Time::now(); while (!designer.isDone()) { printf("elapsed %d [s]\n",(int)(Time::now()-t0)); Time::delay(1.0); } // The design part... printf("Tuning P controller...\n"); Property pControllerRequirements,pController; pControllerRequirements.put("tau",tau); pControllerRequirements.put("K",K); // The bandwidth specification is provided in terms of gain crossover // frequency (in Hz) which amounts to the frequency where the // open loop response given by Kp * plant has a unity-gain; // f_c roughly determines the bandwidth of the closed loop response. // Requirements: track min-jerk profiles whose trajectory // time is 2.0 seconds. // From spectral analysis we know that the most of the // frequency content of a signal composed of the given // min-jerk pulses lies whithin the range [0,0.6] Hz. // A crossover frequency of 0.75 is therefore suitable. pControllerRequirements.put("f_c",0.75); pControllerRequirements.put("type","P"); designer.tuneController(pControllerRequirements,pController); printf("tuning results: %s\n",pController.toString().c_str()); double Kp=pController.find("Kp").asDouble(); printf("found Kp = %g\n",Kp); int scale=4; double Kp_fw=Kp*encoder*(1<<scale); printf("Kp (firmware) = %g; shift factor = %d\n",Kp_fw,scale); // let's identify the stictions values as well Property pStictionEstimation; pStictionEstimation.put("max_time",60.0); // the joint will be controlled under the action // of a high-level PID controller pStictionEstimation.put("Kp",Kp); pStictionEstimation.put("Ki",0.0); pStictionEstimation.put("Kd",0.0); designer.startStictionEstimation(pStictionEstimation); printf("Stiction estimation experiment will last no more than %g seconds...\n", pStictionEstimation.find("max_time").asDouble()); t0=Time::now(); while (!designer.isDone()) { printf("elapsed %d [s]\n",(int)(Time::now()-t0)); Time::delay(1.0); } // retrieve the stiction values designer.getResults(pResults); Vector stiction(2); stiction[0]=pResults.find("stiction").asList()->get(0).asDouble(); stiction[1]=pResults.find("stiction").asList()->get(1).asDouble(); printf("Stiction values: up = %g; down = %g\n",stiction[0],stiction[1]); // now that we know P and stiction, let's try out our controller // against the current version Property pControllerValidation; pControllerValidation.put("max_time",60.0); pControllerValidation.put("Kp",Kp_fw); pControllerValidation.put("scale",scale); ostringstream str; str<<"( "; str<<stiction[0]; str<<" "; str<<stiction[1]; str<<" )"; Value val; val.fromString(str.str().c_str()); pControllerValidation.put("stiction",val); // we let yarp apply the stiction values upon transitions; // by default the "firmware" takes care of it. pControllerValidation.put("stiction_compensation","middleware"); // let's go for the classical "min-jerk" reference input with a // period of 2 seconds. // we have also the "square" waveform at our disposal, just in // case we aim at measuring traditional controller step response. pControllerValidation.put("ref_type","min-jerk"); pControllerValidation.put("ref_period",2.0); // for the "min-jerk" reference type it turns to be useful to // have a "sustain" time where the reference is kept to the // final set-point before switching to the next value. pControllerValidation.put("ref_sustain_time",1.0); // in this experiment both the current controller and our controller // will act, one after other, each for 4 cycles of 1 rising and 1 falling // transition in a row. pControllerValidation.put("cycles_to_switch",4); designer.startControllerValidation(pControllerValidation); printf("Controller validation will last %g seconds...\n", pControllerValidation.find("max_time").asDouble()); t0=Time::now(); while (!designer.isDone()) { printf("elapsed %d [s]\n",(int)(Time::now()-t0)); Time::delay(1.0); } return 0; }
void ValidityDialog::OkPressed() { const KLocale* locale = m_selection->activeSheet()->map()->calculationSettings()->locale(); const ValueParser *const parser = m_selection->activeSheet()->map()->parser(); Validity validity; if (chooseType->currentIndex() == 1) { bool ok; val_min->text().toDouble(&ok); if (! ok) { KMessageBox::error(this , i18n("This is not a valid value."), i18n("Error")); val_min->setText(""); return; } val_max->text().toDouble(&ok); if (! ok && choose->currentIndex() >= 5 && choose->currentIndex() < 7) { KMessageBox::error(this , i18n("This is not a valid value."), i18n("Error")); val_max->setText(""); return; } } else if (chooseType->currentIndex() == 2 || chooseType->currentIndex() == 6) { bool ok; val_min->text().toInt(&ok); if (! ok) { KMessageBox::error(this , i18n("This is not a valid value."), i18n("Error")); val_min->setText(""); return; } val_max->text().toInt(&ok); if (! ok && choose->currentIndex() >= 5 && choose->currentIndex() < 7) { KMessageBox::error(this , i18n("This is not a valid value."), i18n("Error")); val_max->setText(""); return; } } else if (chooseType->currentIndex() == 5) { if (!locale->readTime(val_min->text()).isValid()) { KMessageBox::error(this , i18n("This is not a valid time."), i18n("Error")); val_min->setText(""); return; } if (!locale->readTime(val_max->text()).isValid() && choose->currentIndex() >= 5) { KMessageBox::error(this , i18n("This is not a valid time."), i18n("Error")); val_max->setText(""); return; } } else if (chooseType->currentIndex() == 4) { if (!locale->readDate(val_min->text()).isValid()) { KMessageBox::error(this , i18n("This is not a valid date."), i18n("Error")); val_min->setText(""); return; } if (!locale->readDate(val_max->text()).isValid() && choose->currentIndex() >= 5) { KMessageBox::error(this , i18n("This is not a valid date."), i18n("Error")); val_max->setText(""); return; } } else if (chooseType->currentIndex() == 7) { //Nothing } if (chooseType->currentIndex() == 0) {//no validity validity.setRestriction(Validity::None); validity.setAction(Validity::Stop); validity.setCondition(Conditional::Equal); validity.setMessage(message->toPlainText()); validity.setTitle(title->text()); validity.setMinimumValue(Value()); validity.setMaximumValue(Value()); } else { validity.setRestriction(chooseType->itemData(chooseType->currentIndex()).value<Validity::Restriction>()); validity.setAction(chooseAction->itemData(chooseAction->currentIndex()).value<Validity::Action>()); validity.setCondition(choose->itemData(choose->currentIndex()).value<Conditional::Type>()); validity.setMessage(message->toPlainText()); validity.setTitle(title->text()); validity.setMinimumValue(Value()); validity.setMaximumValue(Value()); if (chooseType->currentIndex() == 1) { if (choose->currentIndex() < 5) { validity.setMinimumValue(Value(val_min->text().toDouble())); } else { validity.setMinimumValue(Value(qMin(val_min->text().toDouble(), val_max->text().toDouble()))); validity.setMaximumValue(Value(qMax(val_max->text().toDouble(), val_min->text().toDouble()))); } } else if (chooseType->currentIndex() == 2 || chooseType->currentIndex() == 6) { if (choose->currentIndex() < 5) { validity.setMinimumValue(Value(val_min->text().toInt())); } else { validity.setMinimumValue(Value(qMin(val_min->text().toInt(), val_max->text().toInt()))); validity.setMaximumValue(Value(qMax(val_max->text().toInt(), val_min->text().toInt()))); } } else if (chooseType->currentIndex() == 4) { const Value minValue = parser->tryParseDate(val_min->text()); const Value maxValue = parser->tryParseDate(val_max->text()); if (choose->currentIndex() < 5) { validity.setMinimumValue(minValue); } else { if (minValue.less(maxValue)) { validity.setMinimumValue(minValue); validity.setMaximumValue(maxValue); } else { validity.setMinimumValue(maxValue); validity.setMaximumValue(minValue); } } } else if (chooseType->currentIndex() == 5) { const Value minValue = parser->tryParseTime(val_min->text()); const Value maxValue = parser->tryParseTime(val_max->text()); if (choose->currentIndex() < 5) { validity.setMinimumValue(minValue); } else { if (minValue.less(maxValue)) { validity.setMaximumValue(maxValue); validity.setMinimumValue(minValue); } else { validity.setMaximumValue(minValue); validity.setMinimumValue(maxValue); } } } else if (chooseType->currentIndex() == 7) { validity.setValidityList(validityList->toPlainText().split('\n', QString::SkipEmptyParts)); } } validity.setDisplayMessage(displayMessage->isChecked()); validity.setAllowEmptyCell(allowEmptyCell->isChecked()); validity.setDisplayValidationInformation(displayHelp->isChecked()); validity.setMessageInfo(messageHelp->toPlainText()); validity.setTitleInfo(titleHelp->text()); ValidityCommand* manipulator = new ValidityCommand(); manipulator->setSheet(m_selection->activeSheet()); manipulator->setValidity(validity); manipulator->add(*m_selection); manipulator->execute(m_selection->canvas()); accept(); }
static JSBool Exception(JSContext *cx, uintN argc, Value *vp) { JSString *message, *filename; JSStackFrame *fp; /* * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when * called as functions, without operator new. But as we do not give * each constructor a distinct JSClass, whose .name member is used by * NewNativeClassInstance to find the class prototype, we must get the * class prototype ourselves. */ JSObject &callee = vp[0].toObject(); Value protov; if (!callee.getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &protov)) return JS_FALSE; if (!protov.isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error"); return JS_FALSE; } JSObject *errProto = &protov.toObject(); JSObject *obj = NewNativeClassInstance(cx, &js_ErrorClass, errProto, errProto->getParent()); if (!obj) return JS_FALSE; /* * If it's a new object of class Exception, then null out the private * data so that the finalizer doesn't attempt to free it. */ if (obj->getClass() == &js_ErrorClass) obj->setPrivate(NULL); /* Set the 'message' property. */ Value *argv = vp + 2; if (argc != 0) { message = js_ValueToString(cx, argv[0]); if (!message) return JS_FALSE; argv[0].setString(message); } else { message = cx->runtime->emptyString; } /* Set the 'fileName' property. */ if (argc > 1) { filename = js_ValueToString(cx, argv[1]); if (!filename) return JS_FALSE; argv[1].setString(filename); fp = NULL; } else { fp = js_GetScriptedCaller(cx, NULL); if (fp) { filename = FilenameToString(cx, fp->script()->filename); if (!filename) return JS_FALSE; } else { filename = cx->runtime->emptyString; } } /* Set the 'lineNumber' property. */ uint32_t lineno; if (argc > 2) { if (!ValueToECMAUint32(cx, argv[2], &lineno)) return JS_FALSE; } else { if (!fp) fp = js_GetScriptedCaller(cx, NULL); lineno = (fp && fp->pc(cx)) ? js_FramePCToLineNumber(cx, fp) : 0; } if (obj->getClass() == &js_ErrorClass && !InitExnPrivate(cx, obj, message, filename, lineno, NULL)) { return JS_FALSE; } vp->setObject(*obj); return JS_TRUE; }
void JSONValue::SetBool(const String& name, bool value) { Value jsonValue; jsonValue.SetBool(value); AddMember(name, jsonValue); }
void ComputeSSO::PrintTainted(std::set<GraphNode*> tainted) { // errs()<<"\n\n Tainted Nodes: "<<tainted.size(); for(set<GraphNode*>::iterator taintNode = tainted.begin();taintNode != tainted.end();++taintNode) { //errs()<<"\n Node Label : "<<(*taintNode)->getLabel(); // errs()<<"--"; if(isa<MemNode>(*taintNode)) { // errs()<<"\n is mem node"; //string nodeLab = (*taintNode)->getLabel(); // string str = "sub_42BC4"; // std::size_t found = nodeLab.find(str); // if (found!=std::string::npos || 1) { MemNode * memNew = dyn_cast<MemNode>(*taintNode); Value * val = memNew->defLocation.second; std::set<Value*> aliases = memNew->getAliases(); if(val) { errs()<<"\n Sink Node Tainted : "<<(*taintNode)->getLabel(); if(isa<Instruction>(val)) { Instruction * inst = dyn_cast<Instruction>(val); string funcName = inst->getParent()->getParent()->getName(); errs()<<"\n Function: "<<funcName; } val->dump(); } if(aliases.size()>0) errs()<<"\n Sink Node Tainted : "<<(*taintNode)->getLabel(); for(set<Value*>::iterator alVal = aliases.begin(); alVal != aliases.end();++alVal) { if(isa<Instruction>(*alVal)) { Instruction * inst = dyn_cast<Instruction>(*alVal); string funcName = inst->getParent()->getParent()->getName(); errs()<<"\n Function: "<<funcName; } (*alVal)->dump(); } } } if(isa<VarNode>(*taintNode)) { VarNode * varNew = dyn_cast<VarNode>(*taintNode); Value * val = varNew->getValue(); //->defLocation.second; if(val) { errs()<<"\n Sink Node Tainted : "<<(*taintNode)->getLabel(); if(isa<Instruction>(val)) { Instruction * inst = dyn_cast<Instruction>(val); string funcName = inst->getParent()->getParent()->getName(); errs()<<"\n Function: "<<funcName; } val->dump(); } } //if } }
void JSONValue::AddInt(int value) { Value jsonValue; jsonValue.SetInt(value); AddMember(jsonValue); }
/// processByValArgument - This is called on every byval argument in call sites. bool MemCpyOpt::processByValArgument(CallSite CS, unsigned ArgNo) { const DataLayout &DL = CS.getCaller()->getParent()->getDataLayout(); // Find out what feeds this byval argument. Value *ByValArg = CS.getArgument(ArgNo); Type *ByValTy = cast<PointerType>(ByValArg->getType())->getElementType(); uint64_t ByValSize = DL.getTypeAllocSize(ByValTy); MemDepResult DepInfo = MD->getPointerDependencyFrom( MemoryLocation(ByValArg, ByValSize), true, CS.getInstruction(), CS.getInstruction()->getParent()); if (!DepInfo.isClobber()) return false; // If the byval argument isn't fed by a memcpy, ignore it. If it is fed by // a memcpy, see if we can byval from the source of the memcpy instead of the // result. MemCpyInst *MDep = dyn_cast<MemCpyInst>(DepInfo.getInst()); if (!MDep || MDep->isVolatile() || ByValArg->stripPointerCasts() != MDep->getDest()) return false; // The length of the memcpy must be larger or equal to the size of the byval. ConstantInt *C1 = dyn_cast<ConstantInt>(MDep->getLength()); if (!C1 || C1->getValue().getZExtValue() < ByValSize) return false; // Get the alignment of the byval. If the call doesn't specify the alignment, // then it is some target specific value that we can't know. unsigned ByValAlign = CS.getParamAlignment(ArgNo+1); if (ByValAlign == 0) return false; // If it is greater than the memcpy, then we check to see if we can force the // source of the memcpy to the alignment we need. If we fail, we bail out. AssumptionCache &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache( *CS->getParent()->getParent()); DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); if (MDep->getAlignment() < ByValAlign && getOrEnforceKnownAlignment(MDep->getSource(), ByValAlign, DL, CS.getInstruction(), &AC, &DT) < ByValAlign) return false; // Verify that the copied-from memory doesn't change in between the memcpy and // the byval call. // memcpy(a <- b) // *b = 42; // foo(*a) // It would be invalid to transform the second memcpy into foo(*b). // // NOTE: This is conservative, it will stop on any read from the source loc, // not just the defining memcpy. MemDepResult SourceDep = MD->getPointerDependencyFrom(MemoryLocation::getForSource(MDep), false, CS.getInstruction(), MDep->getParent()); if (!SourceDep.isClobber() || SourceDep.getInst() != MDep) return false; Value *TmpCast = MDep->getSource(); if (MDep->getSource()->getType() != ByValArg->getType()) TmpCast = new BitCastInst(MDep->getSource(), ByValArg->getType(), "tmpcast", CS.getInstruction()); DEBUG(dbgs() << "MemCpyOpt: Forwarding memcpy to byval:\n" << " " << *MDep << "\n" << " " << *CS.getInstruction() << "\n"); // Otherwise we're good! Update the byval argument. CS.setArgument(ArgNo, TmpCast); ++NumMemCpyInstr; return true; }
void JSONValue::AddFloat(float value) { Value jsonValue; jsonValue.SetDouble((double)value); AddMember(jsonValue); }
/// performCallSlotOptzn - takes a memcpy and a call that it depends on, /// and checks for the possibility of a call slot optimization by having /// the call write its result directly into the destination of the memcpy. bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy, Value *cpyDest, Value *cpySrc, uint64_t cpyLen, unsigned cpyAlign, CallInst *C) { // The general transformation to keep in mind is // // call @func(..., src, ...) // memcpy(dest, src, ...) // // -> // // memcpy(dest, src, ...) // call @func(..., dest, ...) // // Since moving the memcpy is technically awkward, we additionally check that // src only holds uninitialized values at the moment of the call, meaning that // the memcpy can be discarded rather than moved. // Deliberately get the source and destination with bitcasts stripped away, // because we'll need to do type comparisons based on the underlying type. CallSite CS(C); // Require that src be an alloca. This simplifies the reasoning considerably. AllocaInst *srcAlloca = dyn_cast<AllocaInst>(cpySrc); if (!srcAlloca) return false; ConstantInt *srcArraySize = dyn_cast<ConstantInt>(srcAlloca->getArraySize()); if (!srcArraySize) return false; const DataLayout &DL = cpy->getModule()->getDataLayout(); uint64_t srcSize = DL.getTypeAllocSize(srcAlloca->getAllocatedType()) * srcArraySize->getZExtValue(); if (cpyLen < srcSize) return false; // Check that accessing the first srcSize bytes of dest will not cause a // trap. Otherwise the transform is invalid since it might cause a trap // to occur earlier than it otherwise would. if (AllocaInst *A = dyn_cast<AllocaInst>(cpyDest)) { // The destination is an alloca. Check it is larger than srcSize. ConstantInt *destArraySize = dyn_cast<ConstantInt>(A->getArraySize()); if (!destArraySize) return false; uint64_t destSize = DL.getTypeAllocSize(A->getAllocatedType()) * destArraySize->getZExtValue(); if (destSize < srcSize) return false; } else if (Argument *A = dyn_cast<Argument>(cpyDest)) { if (A->getDereferenceableBytes() < srcSize) { // If the destination is an sret parameter then only accesses that are // outside of the returned struct type can trap. if (!A->hasStructRetAttr()) return false; Type *StructTy = cast<PointerType>(A->getType())->getElementType(); if (!StructTy->isSized()) { // The call may never return and hence the copy-instruction may never // be executed, and therefore it's not safe to say "the destination // has at least <cpyLen> bytes, as implied by the copy-instruction", return false; } uint64_t destSize = DL.getTypeAllocSize(StructTy); if (destSize < srcSize) return false; } } else { return false; } // Check that dest points to memory that is at least as aligned as src. unsigned srcAlign = srcAlloca->getAlignment(); if (!srcAlign) srcAlign = DL.getABITypeAlignment(srcAlloca->getAllocatedType()); bool isDestSufficientlyAligned = srcAlign <= cpyAlign; // If dest is not aligned enough and we can't increase its alignment then // bail out. if (!isDestSufficientlyAligned && !isa<AllocaInst>(cpyDest)) return false; // Check that src is not accessed except via the call and the memcpy. This // guarantees that it holds only undefined values when passed in (so the final // memcpy can be dropped), that it is not read or written between the call and // the memcpy, and that writing beyond the end of it is undefined. SmallVector<User*, 8> srcUseList(srcAlloca->user_begin(), srcAlloca->user_end()); while (!srcUseList.empty()) { User *U = srcUseList.pop_back_val(); if (isa<BitCastInst>(U) || isa<AddrSpaceCastInst>(U)) { for (User *UU : U->users()) srcUseList.push_back(UU); continue; } if (GetElementPtrInst *G = dyn_cast<GetElementPtrInst>(U)) { if (!G->hasAllZeroIndices()) return false; for (User *UU : U->users()) srcUseList.push_back(UU); continue; } if (const IntrinsicInst *IT = dyn_cast<IntrinsicInst>(U)) if (IT->getIntrinsicID() == Intrinsic::lifetime_start || IT->getIntrinsicID() == Intrinsic::lifetime_end) continue; if (U != C && U != cpy) return false; } // Check that src isn't captured by the called function since the // transformation can cause aliasing issues in that case. for (unsigned i = 0, e = CS.arg_size(); i != e; ++i) if (CS.getArgument(i) == cpySrc && !CS.doesNotCapture(i)) return false; // Since we're changing the parameter to the callsite, we need to make sure // that what would be the new parameter dominates the callsite. DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); if (Instruction *cpyDestInst = dyn_cast<Instruction>(cpyDest)) if (!DT.dominates(cpyDestInst, C)) return false; // In addition to knowing that the call does not access src in some // unexpected manner, for example via a global, which we deduce from // the use analysis, we also need to know that it does not sneakily // access dest. We rely on AA to figure this out for us. AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); AliasAnalysis::ModRefResult MR = AA.getModRefInfo(C, cpyDest, srcSize); // If necessary, perform additional analysis. if (MR != AliasAnalysis::NoModRef) MR = AA.callCapturesBefore(C, cpyDest, srcSize, &DT); if (MR != AliasAnalysis::NoModRef) return false; // All the checks have passed, so do the transformation. bool changedArgument = false; for (unsigned i = 0; i < CS.arg_size(); ++i) if (CS.getArgument(i)->stripPointerCasts() == cpySrc) { Value *Dest = cpySrc->getType() == cpyDest->getType() ? cpyDest : CastInst::CreatePointerCast(cpyDest, cpySrc->getType(), cpyDest->getName(), C); changedArgument = true; if (CS.getArgument(i)->getType() == Dest->getType()) CS.setArgument(i, Dest); else CS.setArgument(i, CastInst::CreatePointerCast(Dest, CS.getArgument(i)->getType(), Dest->getName(), C)); } if (!changedArgument) return false; // If the destination wasn't sufficiently aligned then increase its alignment. if (!isDestSufficientlyAligned) { assert(isa<AllocaInst>(cpyDest) && "Can only increase alloca alignment!"); cast<AllocaInst>(cpyDest)->setAlignment(srcAlign); } // Drop any cached information about the call, because we may have changed // its dependence information by changing its parameter. MD->removeInstruction(C); // Update AA metadata // FIXME: MD_tbaa_struct and MD_mem_parallel_loop_access should also be // handled here, but combineMetadata doesn't support them yet unsigned KnownIDs[] = { LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope, LLVMContext::MD_noalias, }; combineMetadata(C, cpy, KnownIDs); // Remove the memcpy. MD->removeInstruction(cpy); ++NumMemCpyInstr; return true; }
std::unique_ptr<Spell> parseSpellHelper(const Game& game, const Level& level, const Value& elem, std::string& id) { if (isValidString(elem, "id") == false) { return nullptr; } id = std::string(elem["id"].GetString()); if (isValidId(id) == false) { return nullptr; } if (level.hasClass(id) == true) { return nullptr; } std::unique_ptr<Spell> spell; if (isValidString(elem, "fromId") == true) { std::string fromId(elem["fromId"].GetString()); if (fromId != id) { auto obj = level.getClass<Spell>(fromId); if (obj == nullptr) { return nullptr; } spell = std::make_unique<Spell>(*obj); } } auto texturePack1 = game.Resources().getTexturePack( getStringKey(elem, "texturePack1")); auto texturePack2 = game.Resources().getTexturePack( getStringKey(elem, "texturePack2")); auto textureIndex1 = (size_t)getUIntKey(elem, "textureIndex1"); auto textureIndex2 = (size_t)getUIntKey(elem, "textureIndex2"); if (spell == nullptr) { if (texturePack1 != nullptr && texturePack2 != nullptr) { spell = std::make_unique<Spell>( texturePack1, texturePack2, textureIndex1, textureIndex2); } } else { if (texturePack1 != nullptr) { spell->setTexturePack1(texturePack1); } if (texturePack2 != nullptr) { spell->setTexturePack2(texturePack2); } if (elem.HasMember("textureIndex1") == true) { spell->setTextureIndex1(textureIndex1); } if (elem.HasMember("textureIndex2") == true) { spell->setTextureIndex2(textureIndex2); } } return spell; }
void StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter) { AutoAssertNoGC nogc; uint32_t exprStackSlots = iter.slots() - script()->nfixed; #ifdef TRACK_SNAPSHOTS iter.spewBailingFrom(); #endif IonSpew(IonSpew_Bailouts, " expr stack slots %u, is function frame %u", exprStackSlots, isFunctionFrame()); if (iter.bailoutKind() == Bailout_ArgumentCheck) { // Temporary hack -- skip the (unused) scopeChain, because it could be // bogus (we can fail before the scope chain slot is set). Strip the // hasScopeChain flag and we'll check this later to run prologue(). iter.skip(); flags_ &= ~StackFrame::HAS_SCOPECHAIN; } else { Value v = iter.read(); if (v.isObject()) { scopeChain_ = &v.toObject(); flags_ |= StackFrame::HAS_SCOPECHAIN; if (isFunctionFrame() && fun()->isHeavyweight()) flags_ |= StackFrame::HAS_CALL_OBJ; } else { JS_ASSERT(v.isUndefined()); } } // Assume that all new stack frames have had their entry flag set if // profiling has been turned on. This will be corrected if necessary // elsewhere. if (cx->runtime->spsProfiler.enabled()) setPushedSPSFrame(); if (isFunctionFrame()) { Value thisv = iter.read(); formals()[-1] = thisv; // The new |this| must have already been constructed prior to an Ion // constructor running. if (isConstructing()) JS_ASSERT(!thisv.isPrimitive()); JS_ASSERT(iter.slots() >= CountArgSlots(fun())); IonSpew(IonSpew_Bailouts, " frame slots %u, nargs %u, nfixed %u", iter.slots(), fun()->nargs, script()->nfixed); for (uint32_t i = 0; i < fun()->nargs; i++) { Value arg = iter.read(); formals()[i] = arg; } } exprStackSlots -= CountArgSlots(maybeFun()); for (uint32_t i = 0; i < script()->nfixed; i++) { Value slot = iter.read(); slots()[i] = slot; } IonSpew(IonSpew_Bailouts, " pushing %u expression stack slots", exprStackSlots); FrameRegs ®s = cx->regs(); for (uint32_t i = 0; i < exprStackSlots; i++) { Value v; // If coming from an invalidation bailout, and this is the topmost // value, and a value override has been specified, don't read from the // iterator. Otherwise, we risk using a garbage value. if (!iter.moreFrames() && i == exprStackSlots - 1 && cx->runtime->hasIonReturnOverride()) v = iter.skip(); else v = iter.read(); *regs.sp++ = v; } unsigned pcOff = iter.pcOffset(); regs.pc = script()->code + pcOff; if (iter.resumeAfter()) regs.pc = GetNextPc(regs.pc); IonSpew(IonSpew_Bailouts, " new PC is offset %u within script %p (line %d)", pcOff, (void *)script(), PCToLineNumber(script(), regs.pc)); JS_ASSERT(exprStackSlots == js_ReconstructStackDepth(cx, script(), regs.pc)); }
static void XmlExecuteMultiCall(MethodManager* manager, Value ¶ms, Value &result) { log_debug("ExecuteMultiCall: params= " << params); result.SetSize(params.Size()); for (int i=0; i<(int)params.Size(); i++) { Value singleParams; singleParams.Assign(params[i]); log_debug("Execute index " << i << ": params= " << singleParams); if (!singleParams.IsMap() || !singleParams.HasMember("methodName") || !singleParams["methodName"].IsString() || !singleParams.HasMember("params")) XmlGenerateFaultValue(AnyRpcErrorInvalidRequest, "Invalid request", result[i]); else { Value singleResult; Value methodName = singleParams["methodName"]; try { if (manager->ExecuteMethod(methodName.GetString(),singleParams["params"],singleResult)) { if (singleResult.IsInvalid()) singleResult = ""; result[i][0] = singleResult; } else XmlGenerateFaultValue(AnyRpcErrorMethodNotFound, "Method not found", result[i] ); } catch (const AnyRpcException& fault) { XmlGenerateFaultValue(fault.GetCode(), fault.GetMessage(), result[i]); } } } log_debug("ExecuteMultiCall: result= " << result); }
Object CallRPC(const string& strMethod, const Array& params) { if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") throw runtime_error(strprintf( _("You must set rpcpassword=<password> in the configuration file:\n%s\n" "If the file does not exist, create it with owner-readable-only file permissions."), GetConfigFile().string().c_str())); // Connect to localhost bool fUseSSL = GetBoolArg("-rpcssl", false); asio::io_service io_service; ssl::context context(io_service, ssl::context::sslv23); context.set_options(ssl::context::no_sslv2 | ssl::context::no_sslv3); asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context); SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL); iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d); bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started do { bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))); if (fConnected) break; if (fWait) MilliSleep(1000); else throw runtime_error("couldn't connect to server"); } while (fWait); // HTTP basic authentication string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); map<string, string> mapRequestHeaders; mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64; // Send request string strRequest = JSONRPCRequest(strMethod, params, 1); string strPost = HTTPPost(strRequest, mapRequestHeaders); stream << strPost << std::flush; // Receive HTTP reply status int nProto = 0; int nStatus = ReadHTTPStatus(stream, nProto); // Receive HTTP reply message headers and body map<string, string> mapHeaders; string strReply; ReadHTTPMessage(stream, mapHeaders, strReply, nProto); if (nStatus == HTTP_UNAUTHORIZED) throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) throw runtime_error(strprintf("server returned HTTP error %d", nStatus)); else if (strReply.empty()) throw runtime_error("no response from server"); // Parse reply Value valReply; if (!read_string(strReply, valReply)) throw runtime_error("couldn't parse reply from server"); const Object& reply = valReply.get_obj(); if (reply.empty()) throw runtime_error("expected reply to have result, error and id properties"); return reply; }
/// PromoteAliasSet - Try to promote memory values to scalars by sinking /// stores out of the loop and moving loads to before the loop. We do this by /// looping over the stores in the loop, looking for stores to Must pointers /// which are loop invariant. /// void LICM::PromoteAliasSet(AliasSet &AS) { // We can promote this alias set if it has a store, if it is a "Must" alias // set, if the pointer is loop invariant, and if we are not eliminating any // volatile loads or stores. if (AS.isForwardingAliasSet() || !AS.isMod() || !AS.isMustAlias() || AS.isVolatile() || !CurLoop->isLoopInvariant(AS.begin()->getValue())) return; assert(!AS.empty() && "Must alias set should have at least one pointer element in it!"); Value *SomePtr = AS.begin()->getValue(); // It isn't safe to promote a load/store from the loop if the load/store is // conditional. For example, turning: // // for () { if (c) *P += 1; } // // into: // // tmp = *P; for () { if (c) tmp +=1; } *P = tmp; // // is not safe, because *P may only be valid to access if 'c' is true. // // It is safe to promote P if all uses are direct load/stores and if at // least one is guaranteed to be executed. bool GuaranteedToExecute = false; SmallVector<Instruction*, 64> LoopUses; SmallPtrSet<Value*, 4> PointerMustAliases; // Check that all of the pointers in the alias set have the same type. We // cannot (yet) promote a memory location that is loaded and stored in // different sizes. for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) { Value *ASIV = ASI->getValue(); PointerMustAliases.insert(ASIV); // Check that all of the pointers in the alias set have the same type. We // cannot (yet) promote a memory location that is loaded and stored in // different sizes. if (SomePtr->getType() != ASIV->getType()) return; for (Value::use_iterator UI = ASIV->use_begin(), UE = ASIV->use_end(); UI != UE; ++UI) { // Ignore instructions that are outside the loop. Instruction *Use = dyn_cast<Instruction>(*UI); if (!Use || !CurLoop->contains(Use)) continue; // If there is an non-load/store instruction in the loop, we can't promote // it. if (isa<LoadInst>(Use)) assert(!cast<LoadInst>(Use)->isVolatile() && "AST broken"); else if (isa<StoreInst>(Use)) { assert(!cast<StoreInst>(Use)->isVolatile() && "AST broken"); if (Use->getOperand(0) == ASIV) return; } else return; // Not a load or store. if (!GuaranteedToExecute) GuaranteedToExecute = isSafeToExecuteUnconditionally(*Use); LoopUses.push_back(Use); } } // If there isn't a guaranteed-to-execute instruction, we can't promote. if (!GuaranteedToExecute) return; // Otherwise, this is safe to promote, lets do it! DEBUG(dbgs() << "LICM: Promoting value stored to in loop: " <<*SomePtr<<'\n'); Changed = true; ++NumPromoted; // We use the SSAUpdater interface to insert phi nodes as required. SmallVector<PHINode*, 16> NewPHIs; SSAUpdater SSA(&NewPHIs); // It wants to know some value of the same type as what we'll be inserting. Value *SomeValue; if (isa<LoadInst>(LoopUses[0])) SomeValue = LoopUses[0]; else SomeValue = cast<StoreInst>(LoopUses[0])->getOperand(0); SSA.Initialize(SomeValue->getType(), SomeValue->getName()); // First step: bucket up uses of the pointers by the block they occur in. // This is important because we have to handle multiple defs/uses in a block // ourselves: SSAUpdater is purely for cross-block references. // FIXME: Want a TinyVector<Instruction*> since there is usually 0/1 element. DenseMap<BasicBlock*, std::vector<Instruction*> > UsesByBlock; for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) { Instruction *User = LoopUses[i]; UsesByBlock[User->getParent()].push_back(User); } // Okay, now we can iterate over all the blocks in the loop with uses, // processing them. Keep track of which loads are loading a live-in value. SmallVector<LoadInst*, 32> LiveInLoads; DenseMap<Value*, Value*> ReplacedLoads; for (unsigned LoopUse = 0, e = LoopUses.size(); LoopUse != e; ++LoopUse) { Instruction *User = LoopUses[LoopUse]; std::vector<Instruction*> &BlockUses = UsesByBlock[User->getParent()]; // If this block has already been processed, ignore this repeat use. if (BlockUses.empty()) continue; // Okay, this is the first use in the block. If this block just has a // single user in it, we can rewrite it trivially. if (BlockUses.size() == 1) { // If it is a store, it is a trivial def of the value in the block. if (isa<StoreInst>(User)) { SSA.AddAvailableValue(User->getParent(), cast<StoreInst>(User)->getOperand(0)); } else { // Otherwise it is a load, queue it to rewrite as a live-in load. LiveInLoads.push_back(cast<LoadInst>(User)); } BlockUses.clear(); continue; } // Otherwise, check to see if this block is all loads. If so, we can queue // them all as live in loads. bool HasStore = false; for (unsigned i = 0, e = BlockUses.size(); i != e; ++i) { if (isa<StoreInst>(BlockUses[i])) { HasStore = true; break; } } if (!HasStore) { for (unsigned i = 0, e = BlockUses.size(); i != e; ++i) LiveInLoads.push_back(cast<LoadInst>(BlockUses[i])); BlockUses.clear(); continue; } // Otherwise, we have mixed loads and stores (or just a bunch of stores). // Since SSAUpdater is purely for cross-block values, we need to determine // the order of these instructions in the block. If the first use in the // block is a load, then it uses the live in value. The last store defines // the live out value. We handle this by doing a linear scan of the block. BasicBlock *BB = User->getParent(); Value *StoredValue = 0; for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { if (LoadInst *L = dyn_cast<LoadInst>(II)) { // If this is a load from an unrelated pointer, ignore it. if (!PointerMustAliases.count(L->getOperand(0))) continue; // If we haven't seen a store yet, this is a live in use, otherwise // use the stored value. if (StoredValue) { L->replaceAllUsesWith(StoredValue); ReplacedLoads[L] = StoredValue; } else { LiveInLoads.push_back(L); } continue; } if (StoreInst *S = dyn_cast<StoreInst>(II)) { // If this is a store to an unrelated pointer, ignore it. if (!PointerMustAliases.count(S->getOperand(1))) continue; // Remember that this is the active value in the block. StoredValue = S->getOperand(0); } } // The last stored value that happened is the live-out for the block. assert(StoredValue && "Already checked that there is a store in block"); SSA.AddAvailableValue(BB, StoredValue); BlockUses.clear(); } // Now that all the intra-loop values are classified, set up the preheader. // It gets a load of the pointer we're promoting, and it is the live-out value // from the preheader. LoadInst *PreheaderLoad = new LoadInst(SomePtr,SomePtr->getName()+".promoted", Preheader->getTerminator()); SSA.AddAvailableValue(Preheader, PreheaderLoad); // Now that the preheader is good to go, set up the exit blocks. Each exit // block gets a store of the live-out values that feed them. Since we've // already told the SSA updater about the defs in the loop and the preheader // definition, it is all set and we can start using it. SmallVector<BasicBlock*, 8> ExitBlocks; CurLoop->getUniqueExitBlocks(ExitBlocks); for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { BasicBlock *ExitBlock = ExitBlocks[i]; Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock); Instruction *InsertPos = ExitBlock->getFirstNonPHI(); new StoreInst(LiveInValue, SomePtr, InsertPos); } // Okay, now we rewrite all loads that use live-in values in the loop, // inserting PHI nodes as necessary. for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) { LoadInst *ALoad = LiveInLoads[i]; Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent()); ALoad->replaceAllUsesWith(NewVal); CurAST->copyValue(ALoad, NewVal); ReplacedLoads[ALoad] = NewVal; } // If the preheader load is itself a pointer, we need to tell alias analysis // about the new pointer we created in the preheader block and about any PHI // nodes that just got inserted. if (PreheaderLoad->getType()->isPointerTy()) { // Copy any value stored to or loaded from a must-alias of the pointer. CurAST->copyValue(SomeValue, PreheaderLoad); for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i) CurAST->copyValue(SomeValue, NewPHIs[i]); } // Now that everything is rewritten, delete the old instructions from the body // of the loop. They should all be dead now. for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) { Instruction *User = LoopUses[i]; // If this is a load that still has uses, then the load must have been added // as a live value in the SSAUpdate data structure for a block (e.g. because // the loaded value was stored later). In this case, we need to recursively // propagate the updates until we get to the real value. if (!User->use_empty()) { Value *NewVal = ReplacedLoads[User]; assert(NewVal && "not a replaced load?"); // Propagate down to the ultimate replacee. The intermediately loads // could theoretically already have been deleted, so we don't want to // dereference the Value*'s. DenseMap<Value*, Value*>::iterator RLI = ReplacedLoads.find(NewVal); while (RLI != ReplacedLoads.end()) { NewVal = RLI->second; RLI = ReplacedLoads.find(NewVal); } User->replaceAllUsesWith(NewVal); CurAST->copyValue(User, NewVal); } CurAST->deleteValue(User); User->eraseFromParent(); } // fwew, we're done! }
static JSBool Exception(JSContext *cx, uintN argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); /* * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when * called as functions, without operator new. But as we do not give * each constructor a distinct JSClass, whose .name member is used by * NewNativeClassInstance to find the class prototype, we must get the * class prototype ourselves. */ Value protov; jsid protoAtom = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom); if (!args.callee().getProperty(cx, protoAtom, &protov)) return false; if (!protov.isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, "Error"); return false; } JSObject *errProto = &protov.toObject(); JSObject *obj = NewNativeClassInstance(cx, &ErrorClass, errProto, errProto->getParent()); if (!obj) return false; /* Set the 'message' property. */ JSString *message; if (args.argc() != 0 && !args[0].isUndefined()) { message = js_ValueToString(cx, args[0]); if (!message) return false; args[0].setString(message); } else { message = NULL; } /* Find the scripted caller. */ FrameRegsIter iter(cx); while (!iter.done() && !iter.fp()->isScriptFrame()) ++iter; /* Set the 'fileName' property. */ JSString *filename; if (args.argc() > 1) { filename = js_ValueToString(cx, args[1]); if (!filename) return false; args[1].setString(filename); } else { if (!iter.done()) { filename = FilenameToString(cx, iter.fp()->script()->filename); if (!filename) return false; } else { filename = cx->runtime->emptyString; } } /* Set the 'lineNumber' property. */ uint32_t lineno; if (args.argc() > 2) { if (!ValueToECMAUint32(cx, args[2], &lineno)) return false; } else { lineno = iter.done() ? 0 : js_FramePCToLineNumber(cx, iter.fp(), iter.pc()); } intN exnType = args.callee().getReservedSlot(JSSLOT_ERROR_EXNTYPE).toInt32(); if (!InitExnPrivate(cx, obj, message, filename, lineno, NULL, exnType)) return false; args.rval().setObject(*obj); return true; }