static PTREE genVfunCall( // DIRECTLY GENERATE VFUN CALL target_offset_t vf_offset, // - offset to VF table ptr PTREE node, // - original "this" expression target_offset_t vf_index, // - index into VF table SYMBOL sym ) // - symbol to access { TYPE vfptr_type; // - type[ ptr to VF table ] TYPE vfn_type; // - type[ ptr to VF ] node = NodeBinary( CO_DOT, node, NodeOffset( vf_offset ) ); vfptr_type = MakeVFTableFieldType( TRUE ); node->type = vfptr_type; node->flags |= PTF_LVALUE; node = PtdExprConst( node ); node = NodeRvalue( node ); vfn_type = TypePointedAtModified( vfptr_type ); node = NodeBinary( CO_DOT , node , NodeOffset( vf_index * CgMemorySize( vfn_type ) ) ); node->type = vfn_type; node->flags |= PTF_LVALUE; node = NodeRvalue( node ); node->type = sym->sym_type; return node; }
PTREE NodeConvertVirtualPtr( // EXECUTE A VIRTUAL BASE CAST PTREE expr, // - expr to cast TYPE final_type, // - final type after cast target_offset_t vb_offset, // - offset of vbptr vindex vb_index ) // - index in vbtable { PTREE offset; TYPE vbptr_type; TYPE adjust_type; PTREE dup; vbptr_type = MakeVBTableFieldType( true ); offset = NodeOffset( vb_offset ); expr = NodeBinary( CO_DOT, expr, offset ); expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; expr->type = vbptr_type; dup = NodeDupExpr( &expr ); expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; expr = NodeFetch( expr ); expr->type = vbptr_type; expr->flags &= ~ PTF_LVALUE; expr->flags |= PTF_PTR_NONZERO; adjust_type = TypePointedAtModified( vbptr_type ); offset = NodeOffset( vb_index * CgMemorySize( adjust_type ) ); expr = NodeBinary( CO_DOT, expr, offset ); expr->type = adjust_type; expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; expr = NodeFetch( expr ); expr->type = adjust_type; expr->flags |= PTF_PTR_NONZERO; expr = NodeBinary( CO_DOT, dup, expr ); expr->type = final_type; expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; return( expr ); }
PTREE MakeDeleteCall( // MAKE A CALL TO 'OPERATOR DELETE' SYMBOL del_sym, // - symbol for 'op del' PTREE ptr, // - parm 1 for delete TYPE class_parm ) // - if non-NULL, use size as second parm { PTREE size_arg; // - size argument for call PTREE args; // - arguments for call PTREE expr; // - final expression arg_list *del_args; // - op del arguments del_args = SymFuncArgList( del_sym ); args = NULL; if( class_parm != NULL ) { size_arg = NodeOffset( class_parm->u.c.info->size ); size_arg = NodeConvert( del_args->type_list[1], size_arg ); args = NodeArgument( args, size_arg ); } ptr = NodeConvert( del_args->type_list[0], ptr ); args = NodeArgument( args, ptr ); expr = NodeMakeCall( del_sym, GetBasicType( TYP_VOID ), NULL ); expr = CallArgsArrange( del_sym->sym_type , expr , args , NULL , NULL , NULL ); return expr; }
mozInlineSpellWordUtil::NodeOffset mozInlineSpellWordUtil::MapSoftTextOffsetToDOMPosition(PRInt32 aSoftTextOffset, DOMMapHint aHint) { NS_ASSERTION(mSoftTextValid, "Soft text must be valid if we're to map out of it"); if (!mSoftTextValid) return NodeOffset(nsnull, -1); // The invariant is that the range start..end includes the last mapping, // if any, such that mSoftTextOffset <= aSoftTextOffset PRInt32 start = 0; PRInt32 end = mSoftTextDOMMapping.Length(); while (end - start >= 2) { PRInt32 mid = (start + end)/2; const DOMTextMapping& map = mSoftTextDOMMapping[mid]; if (map.mSoftTextOffset > aSoftTextOffset) { end = mid; } else { start = mid; } } if (start >= end) return NodeOffset(nsnull, -1); // 'start' is now the last mapping, if any, such that // mSoftTextOffset <= aSoftTextOffset. // If we're doing HINT_END, then we may want to return the end of the // the previous mapping instead of the start of this mapping if (aHint == HINT_END && start > 0) { const DOMTextMapping& map = mSoftTextDOMMapping[start - 1]; if (map.mSoftTextOffset + map.mLength == aSoftTextOffset) return NodeOffset(map.mNodeOffset.mNode, map.mNodeOffset.mOffset + map.mLength); } // We allow ourselves to return the end of this mapping even if we're // doing HINT_START. This will only happen if there is no mapping which this // point is the start of. I'm not 100% sure this is OK... const DOMTextMapping& map = mSoftTextDOMMapping[start]; PRInt32 offset = aSoftTextOffset - map.mSoftTextOffset; if (offset >= 0 && offset <= map.mLength) return NodeOffset(map.mNodeOffset.mNode, map.mNodeOffset.mOffset + offset); return NodeOffset(nsnull, -1); }
static PTREE makeTrueFalse( PTREE expr, PTREE op, int value ) { PTREE node; if(( op->flags & PTF_SIDE_EFF ) != 0 ) { return( expr ); } if( anachronismFound( op ) ) { return( expr ); } node = NodeOffset( value ); node = NodeSetBooleanType( node ); node = PTreeCopySrcLocation( node, expr ); NodeFreeDupedExpr( expr ); return( node ); }
nsresult mozInlineSpellWordUtil::SetEnd(nsIDOMNode* aEndNode, PRInt32 aEndOffset) { NS_PRECONDITION(aEndNode, "Null end node?"); NS_ASSERTION(mRootNode, "Not initialized"); InvalidateWords(); if (!IsTextNode(aEndNode)) { // End at the start of the first text node after aEndNode/aEndOffset. aEndNode = FindNextTextNode(aEndNode, aEndOffset, mRootNode); aEndOffset = 0; } mSoftEnd = NodeOffset(aEndNode, aEndOffset); return NS_OK; }
static void adjust_by_delta( // COMPUTE DELTA ADJUSTMENT PTREE *a_expr, // - addr( ptr to be converted ) TYPE base, // - base type unsigned delta, // - adjustment bool positive ) // - true ==> use positive value { PTREE offset; // - node containing delta if( delta == 0 ) { *a_expr = NodeConvert( base, *a_expr ); } else { offset = NodeOffset( delta ); if( ! positive ) { offset->u.int_constant = - delta; } *a_expr = adjust_base_ptr( *a_expr, offset, base ); } }
nsresult mozInlineSpellWordUtil::GetRangeForWord(nsIDOMNode* aWordNode, PRInt32 aWordOffset, nsIDOMRange** aRange) { // Set our soft end and start NodeOffset pt = NodeOffset(aWordNode, aWordOffset); InvalidateWords(); mSoftBegin = mSoftEnd = pt; EnsureWords(); PRInt32 offset = MapDOMPositionToSoftTextOffset(pt); if (offset < 0) return MakeRange(pt, pt, aRange); PRInt32 wordIndex = FindRealWordContaining(offset, HINT_BEGIN, PR_FALSE); if (wordIndex < 0) return MakeRange(pt, pt, aRange); return MakeRangeForWord(mRealWords[wordIndex], aRange); }
nsresult mozInlineSpellWordUtil::SetPosition(nsIDOMNode* aNode, PRInt32 aOffset) { InvalidateWords(); if (!IsTextNode(aNode)) { // Start at the start of the first text node after aNode/aOffset. aNode = FindNextTextNode(aNode, aOffset, mRootNode); aOffset = 0; } mSoftBegin = NodeOffset(aNode, aOffset); EnsureWords(); PRInt32 textOffset = MapDOMPositionToSoftTextOffset(mSoftBegin); if (textOffset < 0) return NS_OK; mNextWordIndex = FindRealWordContaining(textOffset, HINT_END, PR_TRUE); return NS_OK; }
static PTREE DynamicCastVoid // DYNAMIC CAST CODE: VOID * ( CONVCTL* ctl ) // - conversion information { PTREE expr; // - cast expression PTREE from; // - type being case from TOKEN_LOCN locn; // - cast location CLASSINFO *info; // - source (or base class of source) class info expr = ctl->expr; expr = PTreeExtractLocn( expr, &locn ); expr = NodePruneLeftTop( expr ); expr->locn = locn; from = NodeTypeid( ctl->src.pted ); info = GetWithinOffsetOfVFPtr( ctl->src.pted, &expr ); expr = NodeArguments( from , NodeOffset( info->vf_offset ) , expr , NULL ); expr = RunTimeCall( expr, ctl->tgt.orig , RTF_DYN_CAST_VOID ); return( expr ); }
PTREE DynamicCast // DYNAMIC CAST CODE ( CONVCTL* ctl ) // - conversion information { PTREE expr; // - cast expression TOKEN_LOCN locn; // - cast location PTREE from; // - type being cast from PTREE to; // - type being cast to CLASSINFO *info; // - source (or base class of source) class info if( ctl->tgt.pted->id == TYP_VOID ) { return( DynamicCastVoid( ctl ) ); } else { expr = ctl->expr; expr = PTreeExtractLocn( expr, &locn ); expr = NodePruneLeftTop( expr ); expr->locn = locn; from = NodeTypeid( ctl->src.pted ); to = NodeTypeid( ctl->tgt.pted ); info = GetWithinOffsetOfVFPtr( ctl->src.pted, &expr ); expr = NodeArguments( to , from , NodeOffset( info->vf_offset ) , expr , NULL ); DbgAssert( ctl->src.reference == ctl->tgt.reference ); if( ctl->src.reference && ctl->tgt.reference ) { // ref => ref expr = RunTimeCall( expr, ctl->tgt.orig, RTF_DYN_CAST_REF ); } else { // ptr => ptr DbgAssert( !ctl->src.reference && !ctl->tgt.reference ); expr = RunTimeCall( expr, ctl->tgt.orig , RTF_DYN_CAST_PTR ); } } return( expr ); }
void mozInlineSpellWordUtil::BuildSoftText() { // First we have to work backwards from mSoftStart to find a text node // containing a DOM word separator, a non-inline-element // boundary, or the hard start node. That's where we'll start building the // soft string from. nsIDOMNode* node = mSoftBegin.mNode; PRInt32 firstOffsetInNode = 0; PRInt32 checkBeforeOffset = mSoftBegin.mOffset; while (node) { if (ContainsDOMWordSeparator(node, checkBeforeOffset, &firstOffsetInNode)) break; checkBeforeOffset = PR_INT32_MAX; if (IsBreakElement(mCSSView, node)) { // Since FindPrevNode follows tree *preorder*, we're about to traverse // up out of 'node'. Since node induces breaks (e.g., it's a block), // don't bother trying to look outside it, just stop now. break; } node = FindPrevNode(node, mRootNode); } // Now build up the string moving forward through the DOM until we reach // the soft end and *then* see a DOM word separator, a non-inline-element // boundary, or the hard end node. mSoftText.Truncate(); mSoftTextDOMMapping.Clear(); PRBool seenSoftEnd = PR_FALSE; // Leave this outside the loop so large heap string allocations can be reused // across iterations nsAutoString str; while (node) { if (node == mSoftEnd.mNode) { seenSoftEnd = PR_TRUE; } PRBool exit = PR_FALSE; if (IsTextNode(node)) { GetNodeText(node, str); PRInt32 lastOffsetInNode = str.Length(); if (seenSoftEnd) { // check whether we can stop after this for (PRInt32 i = node == mSoftEnd.mNode ? mSoftEnd.mOffset : 0; i < PRInt32(str.Length()); ++i) { if (IsDOMWordSeparator(str.CharAt(i))) { exit = PR_TRUE; // stop at the first separator after the soft end point lastOffsetInNode = i; break; } } } if (firstOffsetInNode < lastOffsetInNode) { PRInt32 len = lastOffsetInNode - firstOffsetInNode; mSoftTextDOMMapping.AppendElement( DOMTextMapping(NodeOffset(node, firstOffsetInNode), mSoftText.Length(), len)); mSoftText.Append(Substring(str, firstOffsetInNode, len)); } firstOffsetInNode = 0; } if (exit) break; CheckLeavingBreakElementClosure closure = { mCSSView, PR_FALSE }; node = FindNextNode(node, mRootNode, CheckLeavingBreakElement, &closure); if (closure.mLeftBreakElement || (node && IsBreakElement(mCSSView, node))) { // We left, or are entering, a break element (e.g., block). Maybe we can // stop now. if (seenSoftEnd) break; // Record the break mSoftText.Append(' '); } } #ifdef DEBUG_SPELLCHECK printf("Got DOM string: %s\n", NS_ConvertUTF16toUTF8(mSoftText).get()); #endif }
void NodeConvertToBasePtr( // CONVERT TO A BASE PTR, USING SEARCH_RESULT PTREE *a_expr, // - addr( ptr to be converted ) TYPE base, // - base type SEARCH_RESULT *result, // - search result bool positive ) // - true ==> use positive value { target_offset_t vb_offset; // - offset of vbptr vindex vb_index; // - index in vbtable target_offset_t delta; // - delta for class PTREE node; // - new node PTREE dup; // - node containing duplicate of original PTREE orig; // - original value TYPE ref_type; // - reference type for original value node = *a_expr; /* references can never be NULL by definition */ ref_type = TypeReference( NodeType( node ) ); if( ref_type != NULL ) { node->flags |= PTF_PTR_NONZERO; } if( node->flags & PTF_MEMORY_EXACT ) { adjust_by_delta( a_expr, base, result->exact_delta, positive ); } else if( result->non_virtual ) { adjust_by_delta( a_expr, base, result->delta, positive ); } else { PTF_FLAG orig_prop; // - flags propogated from original SYMBOL ibp; // - inline bound reference parameter target_offset_t offset; // - offset to ibp #if 0 orig_prop = ( node->flags & PTF_FETCH ) | PTF_LVALUE; #else orig_prop = node->flags & PTF_FETCH; if( NULL != ref_type ) { orig_prop |= PTF_LVALUE; } #endif if( NodeGetIbpSymbol( node, &ibp, &offset ) ) { PTREE expr; // - expression under construction unsigned vb_exact; // - exact offset for conversion vb_exact = result->exact_delta; if( ! positive ) { vb_exact = - vb_exact; } vb_exact += offset; if( NULL == ibp ) { expr = NULL; } else { expr = NodeMakeCallee( ibp ); expr->cgop = CO_IGNORE; } expr = NodeUnary( CO_VBASE_FETCH, expr ); expr = PtdVbaseFetch( expr , result->vb_offset , result->vb_index , result->delta + offset , vb_exact ); expr->type = base; expr->flags = orig_prop; node = NodeReplace( node, expr ); } else { dup = NULL; if( ! NodePtrNonZero( node ) ) { dup = NodeDupExpr( &node ); } vb_offset = result->vb_offset; vb_index = result->vb_index; node = NodeConvertVirtualPtr( node, base, vb_offset, vb_index ); delta = result->delta; if( delta != 0 ) { node = NodeBinary( CO_DOT, node, NodeOffset( delta ) ); node->type = base; node->flags |= orig_prop; } if( dup != NULL ) { orig = NodeDupExpr( &dup ); node = NodeTestExpr( NodeCompareToZero( orig ), node, dup ); } } *a_expr = node; } if( ref_type != NULL ) { (*a_expr)->flags |= PTF_LVALUE; } }
static PTREE transformVaStart // TRANSFORM TO CO_VASTART OPCODE ( PTREE expr ) // - va_start expression { SYMBOL pre_ellipsis_sym; SYMBOL stop; SYMBOL curr; SYMBOL fn; SCOPE caller_arg_scope; unsigned offset; target_size_t arg_size; PTREE arg1; PTREE arg2; PTREE arg3; PTREE valist; // second argument -- must be pre-... parameter arg1 = expr->u.subtree[1]; arg2 = arg1->u.subtree[0]; arg3 = arg2->u.subtree[0]; pre_ellipsis_sym = PTreeOp( &arg2->u.subtree[1] )->u.symcg.symbol; caller_arg_scope = ScopeFunctionScopeInProgress(); fn = ScopeFunction( caller_arg_scope ); offset = 0; if( ObjModelFunctionReturn( fn->sym_type ) == OMR_CLASS_VAL ) { offset += TARGET_PACKING; } if( SymIsThisMember( fn ) ) { offset += TARGET_PACKING; if( SymCDtorExtraParm( fn ) ) { offset += TARGET_PACKING; } } stop = ScopeOrderedStart( caller_arg_scope ); curr = NULL; for(;;) { curr = ScopeOrderedNext( stop, curr ); if( curr == NULL ) { PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL ); return( expr ); } if( ObjModelArgument( curr->sym_type ) == OMR_CLASS_REF ) { arg_size = TARGET_PACKING; } else { arg_size = CgMemorySize( curr->sym_type ); arg_size += TARGET_PACKING - 1; arg_size &= ~( TARGET_PACKING - 1 ); } offset += arg_size; if( curr == pre_ellipsis_sym ) break; } if( ScopeOrderedNext( stop, curr ) != NULL ) { PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL ); return( expr ); } // third argument -- va_list symbol valist = arg1->u.subtree[1]; arg1->u.subtree[1] = NULL; if( arg3->u.subtree[1]->u.int_constant == 0 ) { // compensate for "void *__alist;" arg in <varargs.h> offset -= TARGET_PACKING; } NodeFreeDupedExpr( expr ); expr = NodeBinary( CO_VASTART, valist, NodeOffset( offset ) ); return expr; }