Node* NodeGen::testNLR(smi homeID) { // test if NLR has reached home; the node returned is the success // branch (i.e. the home has been reached), current is the other // branch Node* homeIDTest = NULL; if (homeID) { // note: will be 0 if no inlining if (isImmediate(smiOop(homeID))) { APPEND(new ArithRCNode(SubCCArithOp, nlrHomeIDPR, homeID, noPR)); } else { APPEND(new LoadIntNode(homeID, nlrTempPR)); APPEND(new ArithRRNode(SubCCArithOp, nlrHomeIDPR, nlrTempPR, noPR)); } homeIDTest = APPEND(new BranchNode(EQBranchOp)); APPEND1(new ArithRRNode(SubCCArithOp, nlrHomePR, framePR, noPR)); } else { APPEND (new ArithRRNode(SubCCArithOp, nlrHomePR, framePR, noPR)); } Node* homeFrameTest = APPEND(new BranchNode(EQBranchOp)); // home & homeID match Node* finalReturn = new NopNode; APPEND1(finalReturn); // no match, continue NLR Node* cont = new MergeNode("testNLR cont"); if (homeIDTest) homeIDTest->append(cont); homeFrameTest->append(cont); current = cont; return finalReturn; }
UString JSImmediate::toString(JSValuePtr v) { ASSERT(isImmediate(v)); if (isIntegerNumber(v)) return UString::from(getTruncatedInt32(v)); #if USE(ALTERNATE_JSIMMEDIATE) if (isNumber(v)) { ASSERT(isDoubleNumber(v)); double value = doubleValue(v); if (value == 0.0) // +0.0 or -0.0 return "0"; return UString::from(value); } #else ASSERT(!isNumber(v)); #endif if (jsBoolean(false) == v) return "false"; if (jsBoolean(true) == v) return "true"; if (v.isNull()) return "null"; ASSERT(v.isUndefined()); return "undefined"; }
JSType JSImmediate::type(const JSValue *v) { ASSERT(isImmediate(v)); uintptr_t tag = getTag(v); if (tag == UndefinedType) return v == jsUndefined() ? UndefinedType : NullType; return static_cast<JSType>(tag); }
void SICGenHelper::loadImmediateOop(oop p, Location dest, bool isInt) { assert(isRegister(dest), "must be a register"); if (p == 0) { a->OrR(G0, G0, dest); } else if ((isInt || !p->is_mem()) && isImmediate(smiOop(p))) { a->OrI(G0, (int)p, dest); } else { a->SetHiO(p, dest); // load high part of value a->AddO(dest, p, dest); // add low part } }
JSObject* JSImmediate::prototype(JSValue* v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) return exec->lexicalGlobalObject()->numberPrototype(); if (isBoolean(v)) return exec->lexicalGlobalObject()->booleanPrototype(); JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); exec->setException(exception); return new (exec) JSNotAnObject(exec, exception); }
JSObject* JSImmediate::toObject(JSValue* v, ExecState* exec) { ASSERT(isImmediate(v)); if (isNumber(v)) return constructNumberFromImmediateNumber(exec, v); if (isBoolean(v)) return constructBooleanFromImmediateBoolean(exec, v); JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull()); exec->setException(exception); return new (exec) JSNotAnObject(exec, exception); }
UString JSImmediate::toString(JSValue* v) { ASSERT(isImmediate(v)); if (isNumber(v)) return UString::from(getTruncatedInt32(v)); if (v == jsBoolean(false)) return "false"; if (v == jsBoolean(true)) return "true"; if (v->isNull()) return "null"; ASSERT(v == jsUndefined()); return "undefined"; }
void LoadIntNode::gen() { BasicNode::gen(); if (isRegister(_dest->loc) && isImmediate(smiOop(value))) { theAssembler->OrI(G0, value, _dest->loc); // common case } else if (isRegister(_dest->loc)) { theAssembler->SetHiI(value, _dest->loc); theAssembler->AddI(_dest->loc, value, _dest->loc); } else { theAssembler->SetHiI(value, Temp1); theAssembler->AddI(Temp1, value, Temp1); theAssembler->StoreI(SP, spOffset(_dest->loc), Temp1); } }
JSObject *JSImmediate::toObject(const JSValue *v, ExecState *exec) { assert(isImmediate(v)); if (v == jsNull()) { return throwError(exec, TypeError, "Null value"); } else if (v == jsUndefined()) { return throwError(exec, TypeError, "Undefined value"); } else if (isBoolean(v)) { List args; args.append(const_cast<JSValue *>(v)); return exec->lexicalInterpreter()->builtinBoolean()->construct(exec, args); } else { ASSERT(isNumber(v)); List args; args.append(const_cast<JSValue *>(v)); return exec->lexicalInterpreter()->builtinNumber()->construct(exec, args); } }
UString JSImmediate::toString(const JSValue *v) { ASSERT(isImmediate(v)); if (v == jsNull()) return "null"; else if (v == jsUndefined()) return "undefined"; else if (v == jsBoolean(true)) return "true"; else if (v == jsBoolean(false)) return "false"; else { assert(isNumber(v)); double d = toDouble(v); if (d == 0.0) // +0.0 or -0.0 return "0"; return UString::from(d); } }
void VarSymbol::codegenDef() { GenInfo* info = gGenInfo; if (id == breakOnCodegenID) gdbShouldBreakHere(); // Local variable symbols should never be // generated for extern or void types if (this->hasFlag(FLAG_EXTERN)) return; if (type == dtVoid) return; if( info->cfile ) { codegenDefC(); } else { #ifdef HAVE_LLVM if(isImmediate()) { llvm::GlobalVariable *globalValue = llvm::cast<llvm::GlobalVariable>( info->module->getOrInsertGlobal(cname, type->codegen().type)); globalValue->setConstant(true); if(immediate->const_kind == CONST_KIND_STRING) { if(llvm::Value *constString = codegenImmediateLLVM(immediate)) { llvm::GlobalVariable *globalString = llvm::cast<llvm::GlobalVariable>(constString); globalValue->setInitializer(llvm::cast<llvm::Constant>( info->builder->CreateConstInBoundsGEP2_32( #if HAVE_LLVM_VER >= 37 NULL, #endif globalString, 0, 0))); } else { llvm::GlobalVariable *globalString = new llvm::GlobalVariable( *info->module, llvm::IntegerType::getInt8Ty(info->module->getContext()), true, llvm::GlobalVariable::PrivateLinkage, NULL, "string"); globalString->setInitializer(llvm::Constant::getNullValue( llvm::IntegerType::getInt8Ty(info->module->getContext()))); globalValue->setInitializer(llvm::cast<llvm::Constant>( info->builder->CreateConstInBoundsGEP1_32( #if HAVE_LLVM_VER >= 37 NULL, #endif globalString, 0))); } } else { globalValue->setInitializer(llvm::cast<llvm::Constant>( codegenImmediateLLVM(immediate))); } info->lvt->addGlobalValue(cname, globalValue, GEN_VAL, ! is_signed(type)); } llvm::Type *varType = type->codegen().type; llvm::Value *varAlloca = createTempVarLLVM(varType, cname); info->lvt->addValue(cname, varAlloca, GEN_PTR, ! is_signed(type)); if(AggregateType *ctype = toAggregateType(type)) { if(ctype->isClass() || ctype->symbol->hasFlag(FLAG_WIDE_REF) || ctype->symbol->hasFlag(FLAG_WIDE_CLASS)) { if(isFnSymbol(defPoint->parentSymbol)) { info->builder->CreateStore( llvm::Constant::getNullValue(varType), varAlloca); } } } if(debug_info){ debug_info->get_variable(this); } #endif } }
GenRet VarSymbol::codegenVarSymbol(bool lhsInSetReference) { GenInfo* info = gGenInfo; FILE* outfile = info->cfile; GenRet ret; ret.chplType = typeInfo(); if( outfile ) { // dtString immediates don't actually codegen as immediates, we just use // them for param string functionality. if (immediate && ret.chplType != dtString) { ret.isLVPtr = GEN_VAL; if (immediate->const_kind == CONST_KIND_STRING) { ret.c += '"'; ret.c += immediate->v_string; ret.c += '"'; } else if (immediate->const_kind == NUM_KIND_BOOL) { std::string bstring = (immediate->bool_value())?"true":"false"; const char* castString = "("; switch (immediate->num_index) { case BOOL_SIZE_1: case BOOL_SIZE_SYS: case BOOL_SIZE_8: castString = "UINT8("; break; case BOOL_SIZE_16: castString = "UINT16("; break; case BOOL_SIZE_32: castString = "UINT32("; break; case BOOL_SIZE_64: castString = "UINT64("; break; default: INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index); } ret.c = castString + bstring + ")"; } else if (immediate->const_kind == NUM_KIND_INT) { int64_t iconst = immediate->int_value(); if (iconst == (1ll<<63)) { ret.c = "-INT64(9223372036854775807) - INT64(1)"; } else if (iconst <= -2147483648ll || iconst >= 2147483647ll) { ret.c = "INT64(" + int64_to_string(iconst) + ")"; } else { const char* castString = "("; switch (immediate->num_index) { case INT_SIZE_8: castString = "INT8("; break; case INT_SIZE_16: castString = "INT16("; break; case INT_SIZE_32: castString = "INT32("; break; case INT_SIZE_64: castString = "INT64("; break; default: INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index); } ret.c = castString + int64_to_string(iconst) + ")"; } } else if (immediate->const_kind == NUM_KIND_UINT) { uint64_t uconst = immediate->uint_value(); if( uconst <= (uint64_t) INT32_MAX ) { const char* castString = "("; switch (immediate->num_index) { case INT_SIZE_8: castString = "UINT8("; break; case INT_SIZE_16: castString = "UINT16("; break; case INT_SIZE_32: castString = "UINT32("; break; case INT_SIZE_64: castString = "UINT64("; break; default: INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index); } ret.c = castString + uint64_to_string(uconst) + ")"; } else { ret.c = "UINT64(" + uint64_to_string(uconst) + ")"; } } else { ret.c = cname; // in C, all floating point literals are (double) } } else { // not immediate // is it a constant extern? If it is, it might be for example // an enum or #define'd value, in which case taking the address // of it is simply nonsense. Therefore, we code generate // extern const symbols as GEN_VAL (ie not an lvalue). if( hasFlag(FLAG_CONST) && hasFlag(FLAG_EXTERN) ) { ret.isLVPtr = GEN_VAL; ret.c = cname; } else { QualifiedType qt = qualType(); if (lhsInSetReference) { ret.c = '&'; ret.c += cname; ret.isLVPtr = GEN_PTR; if (qt.isRef() && !qt.isRefType()) ret.chplType = getOrMakeRefTypeDuringCodegen(typeInfo()); else if (qt.isWideRef() && !qt.isWideRefType()) { Type* refType = getOrMakeRefTypeDuringCodegen(typeInfo()); ret.chplType = getOrMakeWideTypeDuringCodegen(refType); } } else { if (qt.isRef() && !qt.isRefType()) { ret.c = cname; ret.isLVPtr = GEN_PTR; } else if(qt.isWideRef() && !qt.isWideRefType()) { ret.c = cname; ret.isLVPtr = GEN_WIDE_PTR; } else { ret.c = '&'; ret.c += cname; ret.isLVPtr = GEN_PTR; } } } // Print string contents in a comment if developer mode // and savec is set. if (developer && 0 != strcmp(saveCDir, "") && immediate && ret.chplType == dtString && immediate->const_kind == CONST_KIND_STRING) { if (strstr(immediate->v_string, "/*") || strstr(immediate->v_string, "*/")) { // Don't emit comment b/c string contained comment character. } else { ret.c += " /* \""; ret.c += immediate->v_string; ret.c += "\" */"; } } } return ret; } else { #ifdef HAVE_LLVM // for LLVM // Handle extern type variables. if( hasFlag(FLAG_EXTERN) && isType() ) { // code generate the type. GenRet got = typeInfo(); return got; } // for nil, generate a void pointer of chplType dtNil // to allow LLVM pointer cast // e.g. T = ( (locale) (nil) ); // // We would just compare against dtNil, but in some cases // the code generator needs to assign e.g. // _ret:dtNil = nil if( typeInfo() == dtNil && 0 == strcmp(cname, "nil") ) { GenRet voidPtr; voidPtr.val = llvm::Constant::getNullValue(info->builder->getInt8PtrTy()); voidPtr.chplType = dtNil; return voidPtr; } if (typeInfo() == dtBool){ // since "true" and "false" are read into the LVT during ReadMacrosAction // they will generate an LLVM value of type i32 instead of i8 if (0 == strcmp(cname, "false")){ GenRet boolVal = new_UIntSymbol(0, INT_SIZE_8)->codegen(); return boolVal; } if (0 == strcmp(cname, "true")){ GenRet boolVal = new_UIntSymbol(1, INT_SIZE_8)->codegen(); return boolVal; } } if(!isImmediate()) { // check LVT for value GenRet got = info->lvt->getValue(cname); got.chplType = typeInfo(); if( got.val ) { return got; } } if(isImmediate()) { ret.isLVPtr = GEN_VAL; if(immediate->const_kind == CONST_KIND_STRING) { if(llvm::Value *value = info->module->getNamedGlobal(name)) { ret.val = value; ret.isLVPtr = GEN_PTR; return ret; } llvm::Value *constString = codegenImmediateLLVM(immediate); llvm::GlobalVariable *globalValue = llvm::cast<llvm::GlobalVariable>( info->module->getOrInsertGlobal (name, info->builder->getInt8PtrTy())); globalValue->setConstant(true); globalValue->setInitializer(llvm::cast<llvm::Constant>( info->builder->CreateConstInBoundsGEP2_32( #if HAVE_LLVM_VER >= 37 NULL, #endif constString, 0, 0))); ret.val = globalValue; ret.isLVPtr = GEN_PTR; } else { ret.val = codegenImmediateLLVM(immediate); } return ret; } if(std::string(cname) == "0") { // Chapel compiler should not make these. INT_FATAL(" zero value BOO "); return ret; } else if (std::string(cname) == "NULL") { GenRet voidPtr; voidPtr.val = llvm::Constant::getNullValue(info->builder->getInt8PtrTy()); voidPtr.chplType = typeInfo(); return voidPtr; } #endif } INT_FATAL("Could not code generate %s - " "perhaps it is a complex macro?", cname); return ret; }
int stm8instructionSize(const lineNode *pl) { char *operand; char *op1start; char *op2start; int i = 0; operand = nextToken(pl->line); op1start = nextToken(NULL); op2start = nextToken(NULL); //fprintf(stderr, "op1start=%s op2start=%s\n", op1start, op2start); while(op2start && isspace(*op2start)) op2start++; //printf("operand=%s op1start=%s op2start=%s\n", operand, op1start, op2start); /* arity=1 */ if(EQUALS(operand, "clr") || EQUALS(operand, "dec") || EQUALS(operand, "inc") || EQUALS(operand, "push") || EQUALS(operand, "swap") || EQUALS(operand, "jp") || EQUALS(operand, "cpl") || EQUALS(operand, "tnz")) { if(!op1start) return(3); if(op1start[0] == 'a' || op1start[1] == 'x') return(1); if(op1start[1] == 'y') return(2); if(op1start[0] == '(') op1start++; if(strstr(op1start, ",y)")) i++; // costs extra byte for operating with y if(isLabel(op1start)) return(3); if(readint(op1start) <= 0xFF) return(2+i); /* op1 > 0xFF */ if(EQUALS(operand, "jp") && !strchr(op1start, 'y')) return(3); return(4); } if(EQUALS(operand, "exg")) { if(isReg(op2start)) return(1); else return(3); } if(EQUALS(operand, "addw") || EQUALS(operand, "subw")) { if(isImmediate(op2start) && op1start[0] == 'y') return(4); if(isImmediate(op2start)) return(3); if(isSpIndexed(op2start)) return(3); if(isLongoff(op2start, "x")) return(4); } if(EQUALS(operand, "cplw")) { if(op1start[0] == 'y') return(2); else return(1); } if(EQUALS(operand, "ldf")) { if(isRelativeAddr(op1start, "y") || isRelativeAddr(op2start, "y")) return(5); else return(4); } /* Operations that costs 2 or 3 bytes for immediate */ if(ISINST(operand, "ld") || EQUALS(operand, "cp") || EQUALS(operand, "cpw") || ISINST(operand, "adc") || EQUALS(operand, "add") || ISINST(operand, "and") || ISINST(operand, "bcp") || ISINST(operand, "call") || ISINST(operand, "callr") || ISINST(operand, "jr") || ISINST(operand, "or") || ISINST(operand, "sbc") || EQUALS(operand, "sub") || ISINST(operand, "xor")) { char suffix; if(!op1start || !op2start) return(4); suffix = operand[strlen(operand)-1]; if(suffix == 'w' && isImmediate(op2start)) i++; // costs extra byte if(isSpIndexed(op1start) || isSpIndexed(op2start)) return(2); if(!strcmp(op1start, "(x)") || !strcmp(op2start, "(x)")) return(1); if(!strcmp(op1start, "(y)") || !strcmp(op2start, "(y)")) return(2); if(isLabel(op1start) || isLabel(op2start)) return(3+i); if(isShortoff(op1start, "x") || isShortoff(op2start, "x")) return(2); if(isShortoff(op1start, "y") || isShortoff(op2start, "y")) return(3); if(isLongoff(op1start, "x") || isLongoff(op2start, "x")) return(3); if(isRelativeAddr(op1start, "y")) return(4); if(strchr(op1start, 'y') || (strchr(op2start, 'y') && !EQUALS(operand, "ldw"))) i++; // costs extra byte for operating with y if(isReg(op1start) && isReg(op2start)) return(1+i); if(op2start[0] == '#') return(2+i); // ld reg, #immd if(readint(op2start) <= 0xFF) return(2+i); return(3+i); } /* mov costs 3, 4 or 5 bytes depending on it's addressing mode */ if(EQUALS(operand, "mov")) { if(op2start && op2start[0] == '#') return(4); if(op2start && isLabel(op2start)) return(5); if(op2start && readint(op2start) <= 0xFF) return(3); if(op2start && readint(op2start) > 0xFF) return(5); } /* Operations that always costs 1 byte */ if(EQUALS(operand, "ccf") || EQUALS(operand, "divw") || EQUALS(operand, "exgw") || EQUALS(operand, "iret") || EQUALS(operand, "nop") || EQUALS(operand, "rcf") || EQUALS(operand, "ret") || EQUALS(operand, "retf") || EQUALS(operand, "rvf") || EQUALS(operand, "scf")) { return(1); } /* Operations that costs 2 or 1 bytes depending on is the Y or X register used */ if(EQUALS(operand, "clrw") || EQUALS(operand, "decw") || EQUALS(operand, "div") || EQUALS(operand, "incw") || EQUALS(operand, "mul") || EQUALS(operand, "negw") || EQUALS(operand, "popw") || EQUALS(operand, "pushw") || EQUALS(operand, "rlcw") || EQUALS(operand, "rlwa") || EQUALS(operand, "rrcw") || EQUALS(operand, "rrwa") || EQUALS(operand, "sllw") || EQUALS(operand, "slaw") || EQUALS(operand, "sraw") || EQUALS(operand, "srlw") || EQUALS(operand, "swapw") || EQUALS(operand, "tnzw")) { if((op1start && !strcmp(op1start, "y")) || (op2start && !strcmp(op2start, "y"))) return(2); else return(1); } return(4); }
Location arith_genHelper(PReg* sreg, PReg* oper, PReg* dest, ArithOpCode op, Location& t1, Location& t2, bool& reversed) { bool haveImmediate = false; reversed = false; oop immediate; if (sreg->isConstPReg()) { oop val = ((ConstPReg*)sreg)->constant; if (val->is_smi() && isImmediate(smiOop(val))) { // try to reverse the sense of the operation switch (op) { case AddArithOp: case AddCCArithOp: case TAddCCArithOp: case AndArithOp: case AndCCArithOp: case OrArithOp: case OrCCArithOp: case XOrArithOp: // commutative operator, no problem sreg = oper; immediate = val; haveImmediate = reversed = true; break; // would need to reverse non-const operand/operation for subtract, // so no savings case SubArithOp: case SubCCArithOp: case TSubCCArithOp: break; case ArithmeticLeftShiftArithOp: case LogicalLeftShiftArithOp: case ArithmeticRightShiftArithOp: case LogicalRightShiftArithOp: // don't bother break; default: ShouldNotReachHere(); // unexpected arith type } } } else if (oper->isConstPReg()) { oop val = ((ConstPReg*)oper)->constant; if (val->is_smi() && isImmediate(smiOop(val))) { immediate = val; haveImmediate = true; } } Location src = genHelper->moveToReg(sreg, Temp1); Location dst = isRegister(dest->loc) ? dest->loc : Temp2; if (haveImmediate) { t1 = src; t2 = G0; int opn = (int)immediate; // for better switch formatting switch (op) { case AddArithOp: theAssembler->AddI(src, opn, dst); break; case SubArithOp: theAssembler->SubI(src, opn, dst); break; case AndArithOp: theAssembler->AndI(src, opn, dst); break; case OrArithOp: theAssembler->OrI (src, opn, dst); break; case XOrArithOp: theAssembler->XorI(src, opn, dst); break; case ArithmeticLeftShiftArithOp: case LogicalLeftShiftArithOp: theAssembler->SllI(src, opn, dst); break; case ArithmeticRightShiftArithOp: theAssembler->SraI(src, opn, dst); break; case LogicalRightShiftArithOp: theAssembler->SrlI(src, opn, dst); break; case AddCCArithOp: theAssembler->AddCCI(src, opn, dst); break; // Do not have to worry about immed being oop (for _Eq:) because SPARC does not // do immediate oops. -- dmu 4/07 case SubCCArithOp: theAssembler->SubCCI(src, opn, dst); break; case AndCCArithOp: theAssembler->AndCCI(src, opn, dst); break; case OrCCArithOp: theAssembler->OrCCI (src, opn, dst); break; case TAddCCArithOp: theAssembler->TAddCCI(src, opn, dst); break; case TSubCCArithOp: theAssembler->TSubCCI(src, opn, dst); break; default: ShouldNotReachHere(); // unexpected arith type } } else { Location src2 = genHelper->moveToReg(oper, Temp2); t1 = src; t2 = src2; switch (op) { case AddArithOp: theAssembler->AddR(src, src2, dst); break; case SubArithOp: theAssembler->SubR(src, src2, dst); break; case AndArithOp: theAssembler->AndR(src, src2, dst); break; case OrArithOp: theAssembler->OrR (src, src2, dst); break; case XOrArithOp: theAssembler->XorR(src, src2, dst); break; case ArithmeticLeftShiftArithOp: case LogicalLeftShiftArithOp: theAssembler->SllR(src, src2, dst); break; case ArithmeticRightShiftArithOp: theAssembler->SraR(src, src2, dst); break; case LogicalRightShiftArithOp: theAssembler->SrlR(src, src2, dst); break; case AddCCArithOp: theAssembler->AddCCR(src, src2, dst); break; case SubCCArithOp: theAssembler->SubCCR(src, src2, dst); break; case AndCCArithOp: theAssembler->AndCCR(src, src2, dst); break; case OrCCArithOp: theAssembler->OrCCR (src, src2, dst); break; case TAddCCArithOp: theAssembler->TAddCCR(src, src2, dst); break; case TSubCCArithOp: theAssembler->TSubCCR(src, src2, dst); break; default: ShouldNotReachHere(); // unexpected arith type } } return dst; }
MailCommon::ScheduledJob *ScheduledArchiveTask::run() { return folder().isValid() ? new ArchiveJob( mManager, mInfo, folder(), isImmediate() ) : 0; }