Value* Builder::createCtlz(Value* value) { ASSERT_TYPE_INTEGER(value); Instruction* i = appendInstr(OPCODE_CTLZ, 0, allocValue(TYPE_I8)); i->src1.setValue(value); return i->dest; }
Value *newClosureValue(Node *t, Env *e) { newClosureValueC++; Value *res = allocValue(); res->type = CLOSURE_VALUE_TYPE; res->data = newClosure(t, e->envValue); res->mark = UNMARKED; return res; }
Value *newBuiltinFun(BuiltinFun f) { newBuiltinFunC++; Value *res = allocValue(); res->type = BUILTIN_FUN_VALUE_TYPE; res->data = f; res->mark = UNMARKED; return res; }
Value *newListValue(List *list) { newListValueC++; Value *res = allocValue(); res->type = LIST_VALUE_TYPE; res->data = list; res->mark = UNMARKED; return res; }
Value *newStringValue(char *s) { newStringValueC++; Value *res = allocValue(); res->type = STRING_VALUE_TYPE; res->data = (void *)s; res->mark = UNMARKED; return res; }
Value *newIntValue(long x) { newIntValueC++; Value *res = allocValue(); res->type = INT_VALUE_TYPE; res->data = (void *)x; res->mark = UNMARKED; return res; }
void NetValue::reallocValue(unsigned char type) { freeValue(); if (m_type != type) { m_type = type; } allocValue(); }
Value *newEnvValue(Env *parent) { newEnvValueC++; Value *res = allocValue(); res->type = ENV_VALUE_TYPE; res->data = newEnv(parent ? parent->envValue : newNoneValue(), res); res->mark = UNMARKED; envPutLocal(res->data, getIntId("this"), res); return res; }
Value* Builder::createNot(Value* value) { if (value->isConstant()) { Value* dest = cloneValue(value); dest->doNot(); return dest; } Instruction* i = appendInstr(OPCODE_NOT, 0, allocValue(value->type)); i->src1.setValue(value); return i->dest; }
Value* Builder::createCall(Function* function, const std::vector<Value*>& args, CallFlags flags) { // Checks assert_true(args.size() == function->typeIn.size()); // Place arguments for (int index = 0; index < args.size(); index++) { assert_true(args[index]->type == function->typeIn[index]); Instruction* i = appendInstr(OPCODE_ARG, 0, allocValue(function->typeIn[index])); i->src1.immediate = index; i->src2.setValue(args[index]); } // Call function Instruction* i; if (function->typeOut == TYPE_VOID) { i = appendInstr(OPCODE_CALL, flags); } else { i = appendInstr(OPCODE_CALL, flags, allocValue(function->typeOut)); } i->src1.function = function; return i->dest; }
Value *newNoneValue() { static Value *res = 0; if (res) { return res; } else { res = allocValue(); res->type = NONE_VALUE_TYPE; res->data = 0; res->mark = UNMARKED; // none is alwaus refed by global env's parent, so it // wil never be GCed. return res; } }
Value* Builder::createTrunc(Value* value, Type type) { if (value->type == type) { return value; } else if (value->isConstant()) { Value* dest = cloneValue(value); dest->doTrunc(type); return dest; } Instruction* i = appendInstr(OPCODE_TRUNC, 0, allocValue(type)); i->src1.setValue(value); return i->dest; }
Value* Builder::createNeg(Value* value) { ASSERT_TYPE_INTEGER(value); if (value->isConstant()) { Value* dest = cloneValue(value); dest->doNeg(); return dest; } Instruction* i = appendInstr(OPCODE_NEG, 0, allocValue(value->type)); i->src1.setValue(value); return i->dest; }
Value* Builder::createSelect(Value* cond, Value* valueTrue, Value* valueFalse) { ASSERT_TYPE_EQUAL(valueTrue, valueFalse); if (cond->isConstant()) { return cond->isConstantTrue() ? valueTrue : valueFalse; } Instruction* i = appendInstr(OPCODE_SELECT, 0, allocValue(valueTrue->type)); i->src1.setValue(cond); i->src2.setValue(valueTrue); i->src3.setValue(valueFalse); return i->dest; }
Value* Builder::createConvert(Value* value, Type type) { if (value->type == type) { return value; } if (value->isConstant()) { Value* dest = cloneValue(value); dest->doConvert(type); return dest; } Instruction* i = appendInstr(OPCODE_CONVERT, 0, allocValue(type)); i->src1.setValue(value); return i->dest; }
// Comparison operations Value* Builder::createCmp(Value* lhs, Value* rhs, CompareFlags flags) { ASSERT_TYPE_EQUAL(lhs, rhs); if (lhs->isConstant() && rhs->isConstant()) { Value* dest = cloneValue(lhs); dest->doCompare(rhs, flags); return dest; } Instruction* i = appendInstr(OPCODE_CMP, flags, allocValue(TYPE_I8)); i->src1.setValue(lhs); i->src2.setValue(rhs); return i->dest; }
Value* Builder::createFNeg(Value* value) { ASSERT_TYPE_FLOAT(value); if (value->isConstant()) { Value* dest = cloneValue(value); assert_always("Unimplemented"); //dest->doFNeg(); return dest; } Instruction* i = appendInstr(OPCODE_FNEG, 0, allocValue(value->type)); i->src1.setValue(value); return i->dest; }
Value* Builder::createDiv(Value* lhs, Value* rhs, ArithmeticFlags flags) { ASSERT_TYPE_INTEGER(lhs); ASSERT_TYPE_EQUAL(lhs, rhs); if (lhs->isConstant() && rhs->isConstant()) { Value* dest = cloneValue(lhs); dest->doDiv(rhs, flags); return dest; } Instruction* i = appendInstr(OPCODE_DIV, flags, allocValue(lhs->type)); i->src1.setValue(lhs); i->src2.setValue(rhs); return i->dest; }
StringValue *StringTable::insert(const char *s, size_t length) { const hash_t hash = calcHash(s, length); size_t i = findSlot(hash, s, length); if (table[i].vptr) return NULL; // already in table if (++count > tabledim * loadFactor) { grow(); i = findSlot(hash, s, length); } table[i].hash = hash; table[i].vptr = allocValue(s, length); // printf("insert %.*s %p\n", (int)length, s, table[i].value ?: NULL); return getValue(table[i].vptr); }
Value* Builder::createFDiv(Value* lhs, Value* rhs) { ASSERT_TYPE_FLOAT(lhs); ASSERT_TYPE_EQUAL(lhs, rhs); if (lhs->isConstant() && rhs->isConstant()) { Value* dest = cloneValue(lhs); assert_always("Unimplemented"); //dest->doDiv(rhs); return dest; } Instruction* i = appendInstr(OPCODE_FDIV, 0, allocValue(lhs->type)); i->src1.setValue(lhs); i->src2.setValue(rhs); return i->dest; }
StringValue *StringTable::update(const char *s, size_t length) { const hash_t hash = calcHash(s, length); size_t i = findSlot(hash, s, length); if (!table[i].vptr) { if (++count > tabledim * loadFactor) { grow(); i = findSlot(hash, s, length); } table[i].hash = hash; table[i].vptr = allocValue(s, length); } // printf("update %.*s %p\n", (int)length, s, table[i].value ?: NULL); return getValue(table[i].vptr); }
Value* Builder::createSub(Value* lhs, Value* rhs) { ASSERT_TYPE_INTEGER(lhs); ASSERT_TYPE_EQUAL(lhs, rhs); if (rhs->isConstantZero()) { return lhs; } else if (lhs->isConstant() && rhs->isConstant()) { Value* dest = cloneValue(lhs); dest->doSub(rhs); return dest; } Instruction* i = appendInstr(OPCODE_SUB, 0, allocValue(lhs->type)); i->src1.setValue(lhs); i->src2.setValue(rhs); return i->dest; }
Value* Builder::createXor(Value* lhs, Value* rhs) { ASSERT_TYPE_EQUAL(lhs, rhs); if (lhs == rhs) { // TODO } else if (lhs->isConstantZero()) { return lhs; } else if (rhs->isConstantZero()) { return rhs; } else if (lhs->isConstant() && rhs->isConstant()) { Value* dest = cloneValue(lhs); dest->doXor(rhs); return dest; } Instruction* i = appendInstr(OPCODE_XOR, 0, allocValue(lhs->type)); i->src1.setValue(lhs); i->src2.setValue(rhs); return i->dest; }
Value* Builder::createShrA(Value* value, Value* amount) { ASSERT_TYPE_INTEGER(value); ASSERT_TYPE_INTEGER(amount); if (amount->isConstantZero()) { return value; } if (value->isConstant() && amount->isConstant()) { Value* dest = cloneValue(value); dest->doShrA(amount); return dest; } if (amount->type != TYPE_I8) { amount = createTrunc(amount, TYPE_I8); } Instruction* i = appendInstr(OPCODE_SHRA, 0, allocValue(value->type)); i->src1.setValue(value); i->src2.setValue(amount); return i->dest; }
Value* ValFrac(Fraction* frac) { Value* ret = allocValue(VAL_FRAC); ret->frac = frac; Fraction_reduce(ret); return ret; }
Value* ValExpr(BinOp* expr) { Value* ret = allocValue(VAL_EXPR); ret->expr = expr; return ret; }
Value* ValUnary(UnOp* term) { Value* ret = allocValue(VAL_UNARY); ret->term = term; return ret; }
Value* ValCall(FuncCall* call) { Value* ret = allocValue(VAL_CALL); ret->call = call; return ret; }
void allocValue(Program &prog, CallType ctypeVec) {allocValue(prog, &ctypeVec, 1);}
void allocValue(Program &prog, CallType const (&ctypeVec)[ctypeLen]) {allocValue(prog, ctypeVec, ctypeLen);}