@@ -4550,7 +4550,7 @@ void CheerpWriter::compileLoad(const LoadInst& li, PARENT_PRIORITY parentPrio)
45504550 needsCheckBounds = true ;
45514551 bool needsOffset = !li.use_empty () && Ty->isPointerTy () && PA.getPointerKindAssert (&li) == SPLIT_REGULAR && !PA.getConstantOffsetForPointer (&li);
45524552 stream<<" (" ;
4553- compileCheckDefined (ptrOp, needsOffset);
4553+ compileCheckMemberExists (ptrOp, needsOffset);
45544554 stream<<" ," ;
45554555 }
45564556 }
@@ -4765,7 +4765,7 @@ void CheerpWriter::compileStore(const StoreInst& si)
47654765 else if (ptrKind == COMPLETE_OBJECT && isGEP (ptrOp))
47664766 {
47674767 bool needsOffset = Ty->isPointerTy () && PA.getPointerKindAssert (&si) == SPLIT_REGULAR && !PA.getConstantOffsetForPointer (&si);
4768- compileCheckDefined (ptrOp, needsOffset);
4768+ compileCheckMemberExists (ptrOp, needsOffset);
47694769 stream<<" ," ;
47704770 }
47714771 }
@@ -6257,20 +6257,46 @@ void CheerpWriter::compileCheckBounds(const Value* p)
62576257 stream<<" )" ;
62586258}
62596259
6260- void CheerpWriter::compileCheckDefinedHelper ()
6260+ void CheerpWriter::compileCheckMemberExistsHelper ()
62616261{
6262- stream << " function checkDefined(m ){if(m===undefined) throw new Error('UndefinedMemberAccess ');}" << NewLine;
6262+ stream << " function checkMemberExists(obj, member ){if(!(member in obj)) throw new Error('MemberDoesNotExist ');}" << NewLine;
62636263}
62646264
6265- void CheerpWriter::compileCheckDefined (const Value* p, bool needsOffset)
6265+ void CheerpWriter::compileCheckMemberExists (const Value* p, bool needsOffset)
62666266{
6267- // When compiling a SPIT_REGULAR, if there is an offset, we only check that.
6268- // If the offset exists the base is guaranteed to exists in the type.
6269- stream<<" checkDefined(" ;
6270- compileGEP (cast<User>(p),COMPLETE_OBJECT, HIGHEST);
6271- if (needsOffset)
6272- stream << " o" ;
6273- stream<<" )" ;
6267+ const llvm::User* gep_inst = cast<User>(p);
6268+ SmallVector< const Value*, 8 > indices (std::next (gep_inst->op_begin ()), gep_inst->op_end ());
6269+ Type* basePointedType = cast<GEPOperator>(gep_inst)->getSourceElementType ();
6270+
6271+ StructType* containerStructType = dyn_cast<StructType>(GetElementPtrInst::getIndexedType (basePointedType,
6272+ makeArrayRef (const_cast <Value* const *>(indices.begin ()),
6273+ const_cast <Value* const *>(indices.end () - 1 ))));
6274+
6275+ if (containerStructType && indices.size () > 1 )
6276+ assert (isa<ConstantInt>(indices.back ()));
6277+
6278+ stream << " checkMemberExists(" ;
6279+ compileCompleteObject (gep_inst->getOperand (0 ), indices.front ());
6280+
6281+ compileAccessToElement (basePointedType, makeArrayRef (std::next (indices.begin ()), std::prev (indices.end ())), false );
6282+ stream << " , " ;
6283+ const Value* lastOperand = gep_inst->getOperand (gep_inst->getNumOperands () - 1 );
6284+
6285+ if (containerStructType)
6286+ {
6287+ const APInt& index = cast<Constant>(lastOperand)->getUniqueInteger ();
6288+ uint64_t idxVal = index.getLimitedValue ();
6289+
6290+ stream << " '" ;
6291+ stream << types.getPrefixCharForMember (PA, containerStructType, idxVal) << idxVal;
6292+ if (needsOffset)
6293+ stream << " o" ;
6294+ stream << " '" ;
6295+ }
6296+ else if (dyn_cast<ArrayType>(basePointedType))
6297+ compileOperand (lastOperand, LOWEST);
6298+
6299+ stream << " )" ;
62746300}
62756301
62766302void CheerpWriter::compileCheckBoundsAsmJSHelper ()
@@ -6617,7 +6643,7 @@ void CheerpWriter::compileHelpers()
66176643 if ( checkBounds )
66186644 {
66196645 compileCheckBoundsHelper ();
6620- compileCheckDefinedHelper ();
6646+ compileCheckMemberExistsHelper ();
66216647 }
66226648
66236649 compileBuiltins (false );
0 commit comments