Skip to content

Commit c890744

Browse files
Andres Madrid Uchaalexp-sssup
authored andcommitted
CheerpWriter: changed checkDefined to checkMemberExists
The previous logic of checkDefined was causing issues when compiling with the no-optimization flag together with -cheep-bounds-check. Instead of checking if a value is undefined and throwing an error, it is better to check if the member of an object exists.
1 parent d3f04e4 commit c890744

File tree

2 files changed

+41
-15
lines changed

2 files changed

+41
-15
lines changed

llvm/include/llvm/Cheerp/Writer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,11 @@ class CheerpWriter final : public CheerpBaseWriter
750750
/**
751751
* Compile a function to assure a GEP property access is defined
752752
*/
753-
void compileCheckDefined(const llvm::Value* p, bool needsOffset);
753+
void compileCheckMemberExists(const llvm::Value* p, bool needsOffset);
754754
/**
755755
* Compile a function for checking if a reference is defined
756756
*/
757-
void compileCheckDefinedHelper();
757+
void compileCheckMemberExistsHelper();
758758
/**
759759
* Compile a JS string while escaping special characters
760760
*/

llvm/lib/CheerpWriter/CheerpWriter.cpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

62766302
void 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

Comments
 (0)