void emitSetS(IRGS& env) { auto const ssaPropName = topC(env, BCSPOffset{2}); if (!ssaPropName->isA(TStr)) { PUNT(SetS-PropNameNotString); } auto const value = popC(env, DataTypeCountness); auto const ssaCls = popA(env); auto const propAddr = ldClsPropAddr(env, ssaCls, ssaPropName, true); auto const ptr = gen(env, UnboxPtr, propAddr); destroyName(env, ssaPropName); bindMem(env, ptr, value); }
void emitCGetS(HTS& env) { auto const ssaPropName = topC(env, BCSPOffset{1}); if (!ssaPropName->isA(Type::Str)) { PUNT(CGetS-PropNameNotString); } auto const ssaCls = popA(env); auto const propAddr = ldClsPropAddr(env, ssaCls, ssaPropName, true); auto const unboxed = gen(env, UnboxPtr, propAddr); auto const ldMem = gen(env, LdMem, unboxed->type().deref(), unboxed); destroyName(env, ssaPropName); pushIncRef(env, ldMem); }
void emitIssetG(IRGS& env) { auto const name = topC(env, BCSPOffset{0}); if (!name->isA(TStr)) PUNT(IssetG-NameNotStr); auto const ret = cond( env, [&] (Block* taken) { return gen(env, LdGblAddr, taken, name); }, [&] (SSATmp* ptr) { // Next: global exists return gen(env, IsNTypeMem, TNull, gen(env, UnboxPtr, ptr)); }, [&] { // Taken: global doesn't exist return cns(env, false); } ); destroyName(env, name); push(env, ret); }
void emitVGetS(IRGS& env) { auto const ssaPropName = topC(env, BCSPOffset{1}); if (!ssaPropName->isA(TStr)) { PUNT(VGetS-PropNameNotString); } auto const ssaCls = popA(env); auto const propAddr = ldClsPropAddr(env, ssaCls, ssaPropName, true); destroyName(env, ssaPropName); auto const val = gen( env, LdMem, TBoxedInitCell, gen(env, BoxPtr, propAddr) ); pushIncRef(env, val); }
void emitEmptyG(IRGS& env) { auto const name = topC(env); if (!name->isA(TStr)) PUNT(EmptyG-NameNotStr); auto const ret = cond( env, [&] (Block* taken) { return gen(env, LdGblAddr, taken, name); }, [&] (SSATmp* ptr) { // Next: global exists auto const unboxed = gen(env, UnboxPtr, ptr); auto const val = gen(env, LdMem, TCell, unboxed); return gen(env, XorBool, gen(env, ConvCellToBool, val), cns(env, true)); }, [&] { // Taken: global doesn't exist return cns(env, true); }); destroyName(env, name); push(env, ret); }
void emitCGetQuietG(IRGS& env) { auto const name = topC(env); if (!name->isA(TStr)) PUNT(CGetQuietG-NonStrName); auto ret = cond( env, [&] (Block* taken) { return gen(env, LdGblAddr, taken, name); }, [&] (SSATmp* ptr) { auto tmp = gen(env, LdMem, TCell, gen(env, UnboxPtr, ptr)); gen(env, IncRef, tmp); return tmp; }, // Taken: LdGblAddr branched here because no global variable exists with // that name. [&] { return cns(env, TInitNull); } ); destroyName(env, name); push(env, ret); }
void emitIssetS(IRGS& env) { auto const ssaPropName = topC(env, BCSPOffset{1}); if (!ssaPropName->isA(TStr)) { PUNT(IssetS-PropNameNotString); } auto const ssaCls = popA(env); auto const ret = cond( env, [&] (Block* taken) { auto propAddr = ldClsPropAddr(env, ssaCls, ssaPropName, false); return gen(env, CheckNonNull, taken, propAddr); }, [&] (SSATmp* ptr) { // Next: property or global exists return gen(env, IsNTypeMem, TNull, gen(env, UnboxPtr, ptr)); }, [&] { // Taken: LdClsPropAddr* returned Nullptr because it isn't defined return cns(env, false); } ); destroyName(env, ssaPropName); push(env, ret); }