update dev300-m58
[ooovba.git] / basic / source / comp / codegen.cxx
blobc9a14617b5971b77ed13b2a45fc2928006a44d73
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: codegen.cxx,v $
10 * $Revision: 1.20 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #include <basic/sbx.hxx>
35 #include "sbcomp.hxx"
36 #include "image.hxx"
37 #include <limits>
39 // nInc ist die Inkrementgroesse der Puffer
41 SbiCodeGen::SbiCodeGen( SbModule& r, SbiParser* p, short nInc )
42 : rMod( r ), aCode( p, nInc )
44 pParser = p;
45 bStmnt = FALSE;
46 nLine = 0;
47 nCol = 0;
48 nForLevel = 0;
51 UINT32 SbiCodeGen::GetPC()
53 return aCode.GetSize();
56 // Statement merken
58 void SbiCodeGen::Statement()
60 bStmnt = TRUE;
62 nLine = pParser->GetLine();
63 nCol = pParser->GetCol1();
65 // #29955 Information der for-Schleifen-Ebene
66 // in oberen Byte der Spalte speichern
67 nCol = (nCol & 0xff) + 0x100 * nForLevel;
70 // Anfang eines Statements markieren
72 void SbiCodeGen::GenStmnt()
74 if( bStmnt )
76 bStmnt = FALSE;
77 Gen( _STMNT, nLine, nCol );
81 // Die Gen-Routinen returnen den Offset des 1. Operanden,
82 // damit Jumps dort ihr Backchain versenken koennen
84 UINT32 SbiCodeGen::Gen( SbiOpcode eOpcode )
86 #ifndef PRODUCT
87 if( eOpcode < SbOP0_START || eOpcode > SbOP0_END )
88 pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE1" );
89 #endif
90 GenStmnt();
91 aCode += (UINT8) eOpcode;
92 return GetPC();
95 UINT32 SbiCodeGen::Gen( SbiOpcode eOpcode, UINT32 nOpnd )
97 #ifndef PRODUCT
98 if( eOpcode < SbOP1_START || eOpcode > SbOP1_END )
99 pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE2" );
100 #endif
101 GenStmnt();
102 aCode += (UINT8) eOpcode;
103 UINT32 n = GetPC();
104 aCode += nOpnd;
105 return n;
108 UINT32 SbiCodeGen::Gen( SbiOpcode eOpcode, UINT32 nOpnd1, UINT32 nOpnd2 )
110 #ifndef PRODUCT
111 if( eOpcode < SbOP2_START || eOpcode > SbOP2_END )
112 pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE3" );
113 #endif
114 GenStmnt();
115 aCode += (UINT8) eOpcode;
116 UINT32 n = GetPC();
117 aCode += nOpnd1;
118 aCode += nOpnd2;
119 return n;
122 // Abspeichern des erzeugten Images im Modul
124 void SbiCodeGen::Save()
126 SbiImage* p = new SbiImage;
127 rMod.StartDefinitions();
128 // OPTION BASE-Wert:
129 p->nDimBase = pParser->nBase;
130 // OPTION EXPLICIT-Flag uebernehmen
131 if( pParser->bExplicit )
132 p->SetFlag( SBIMG_EXPLICIT );
134 int nIfaceCount = 0;
135 if( rMod.mnType == com::sun::star::script::ModuleType::Class )
137 OSL_TRACE("COdeGen::save() classmodule processing");
138 rMod.bIsProxyModule = true;
139 p->SetFlag( SBIMG_CLASSMODULE );
140 pCLASSFAC->AddClassModule( &rMod );
142 nIfaceCount = pParser->aIfaceVector.size();
143 if( nIfaceCount )
145 if( !rMod.pClassData )
146 rMod.pClassData = new SbClassData;
148 for( int i = 0 ; i < nIfaceCount ; i++ )
150 const String& rIfaceName = pParser->aIfaceVector[i];
151 SbxVariable* pIfaceVar = new SbxVariable( SbxVARIANT );
152 pIfaceVar->SetName( rIfaceName );
153 SbxArray* pIfaces = rMod.pClassData->mxIfaces;
154 pIfaces->Insert( pIfaceVar, pIfaces->Count() );
158 else
160 pCLASSFAC->RemoveClassModule( &rMod );
161 // Only a ClassModule can revert to Normal
162 if ( rMod.mnType == com::sun::star::script::ModuleType::Class )
163 rMod.mnType = com::sun::star::script::ModuleType::Normal;
164 rMod.bIsProxyModule = false;
166 if( pParser->bText )
167 p->SetFlag( SBIMG_COMPARETEXT );
168 // GlobalCode-Flag
169 if( pParser->HasGlobalCode() )
170 p->SetFlag( SBIMG_INITCODE );
171 // Die Entrypoints:
172 for( SbiSymDef* pDef = pParser->aPublics.First(); pDef;
173 pDef = pParser->aPublics.Next() )
175 SbiProcDef* pProc = pDef->GetProcDef();
176 if( pProc && pProc->IsDefined() )
178 String aProcName = pProc->GetName();
179 String aIfaceProcName;
180 String aIfaceName;
181 USHORT nPassCount = 1;
182 if( nIfaceCount )
184 int nPropPrefixFound =
185 aProcName.Search( String( RTL_CONSTASCII_USTRINGPARAM("Property ") ) );
186 String aPureProcName = aProcName;
187 String aPropPrefix;
188 if( nPropPrefixFound == 0 )
190 aPropPrefix = aProcName.Copy( 0, 13 ); // 13 == Len( "Property ?et " )
191 aPureProcName = aProcName.Copy( 13 );
193 for( int i = 0 ; i < nIfaceCount ; i++ )
195 const String& rIfaceName = pParser->aIfaceVector[i];
196 int nFound = aPureProcName.Search( rIfaceName );
197 if( nFound == 0 && '_' == aPureProcName.GetChar( rIfaceName.Len() ) )
199 if( nPropPrefixFound == 0 )
200 aIfaceProcName += aPropPrefix;
201 aIfaceProcName += aPureProcName.Copy( rIfaceName.Len() + 1 );
202 aIfaceName = rIfaceName;
203 nPassCount = 2;
204 break;
208 SbMethod* pMeth = NULL;
209 for( USHORT nPass = 0 ; nPass < nPassCount ; nPass++ )
211 if( nPass == 1 )
212 aProcName = aIfaceProcName;
214 PropertyMode ePropMode = pProc->getPropertyMode();
215 if( ePropMode != PROPERTY_MODE_NONE )
217 SbxDataType ePropType = SbxEMPTY;
218 switch( ePropMode )
220 case PROPERTY_MODE_GET:
221 ePropType = pProc->GetType();
222 break;
223 case PROPERTY_MODE_LET:
225 // type == type of first parameter
226 ePropType = SbxVARIANT; // Default
227 SbiSymPool* pPool = &pProc->GetParams();
228 if( pPool->GetSize() > 1 )
230 SbiSymDef* pPar = pPool->Get( 1 );
231 if( pPar )
232 ePropType = pPar->GetType();
234 break;
236 case PROPERTY_MODE_SET:
237 ePropType = SbxOBJECT;
238 break;
239 case PROPERTY_MODE_NONE:
240 DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" );
241 break;
243 String aPropName = pProc->GetPropName();
244 if( nPass == 1 )
245 aPropName = aPropName.Copy( aIfaceName.Len() + 1 );
246 SbProcedureProperty* pProcedureProperty = NULL;
247 OSL_TRACE("*** getProcedureProperty for thing %s",
248 rtl::OUStringToOString( aPropName,RTL_TEXTENCODING_UTF8 ).getStr() );
249 pProcedureProperty = rMod.GetProcedureProperty( aPropName, ePropType );
251 if( nPass == 1 )
253 SbIfaceMapperMethod* pMapperMeth = NULL;
254 pMapperMeth = rMod.GetIfaceMapperMethod( aProcName, pMeth );
256 else
258 pMeth = rMod.GetMethod( aProcName, pProc->GetType() );
260 // #110004
261 if( !pProc->IsPublic() )
262 pMeth->SetFlag( SBX_PRIVATE );
264 pMeth->nStart = pProc->GetAddr();
265 pMeth->nLine1 = pProc->GetLine1();
266 pMeth->nLine2 = pProc->GetLine2();
267 // Die Parameter:
268 SbxInfo* pInfo = pMeth->GetInfo();
269 String aHelpFile, aComment;
270 ULONG nHelpId = 0;
271 if( pInfo )
273 // Die Zusatzdaten retten
274 aHelpFile = pInfo->GetHelpFile();
275 aComment = pInfo->GetComment();
276 nHelpId = pInfo->GetHelpId();
278 // Und die Parameterliste neu aufbauen
279 pInfo = new SbxInfo( aHelpFile, nHelpId );
280 pInfo->SetComment( aComment );
281 SbiSymPool* pPool = &pProc->GetParams();
282 // Das erste Element ist immer der Funktionswert!
283 for( USHORT i = 1; i < pPool->GetSize(); i++ )
285 SbiSymDef* pPar = pPool->Get( i );
286 SbxDataType t = pPar->GetType();
287 if( !pPar->IsByVal() )
288 t = (SbxDataType) ( t | SbxBYREF );
289 if( pPar->GetDims() )
290 t = (SbxDataType) ( t | SbxARRAY );
291 // #33677 Optional-Info durchreichen
292 USHORT nFlags = SBX_READ;
293 if( pPar->IsOptional() )
294 nFlags |= SBX_OPTIONAL;
296 pInfo->AddParam( pPar->GetName(), t, nFlags );
298 UINT32 nUserData = 0;
299 USHORT nDefaultId = pPar->GetDefaultId();
300 if( nDefaultId )
301 nUserData |= nDefaultId;
302 if( pPar->IsParamArray() )
303 nUserData |= PARAM_INFO_PARAMARRAY;
304 if( nUserData )
306 SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i );
307 pParam->nUserData = nUserData;
310 pMeth->SetInfo( pInfo );
313 } // for( iPass...
316 // Der Code
317 p->AddCode( aCode.GetBuffer(), aCode.GetSize() );
319 // Der globale StringPool. 0 ist nicht belegt.
320 SbiStringPool* pPool = &pParser->aGblStrings;
321 USHORT nSize = pPool->GetSize();
322 p->MakeStrings( nSize );
323 USHORT i;
324 for( i = 1; i <= nSize; i++ )
325 p->AddString( pPool->Find( i ) );
327 // Typen einfuegen
328 USHORT nCount = pParser->rTypeArray->Count();
329 for (i = 0; i < nCount; i++)
330 p->AddType((SbxObject *)pParser->rTypeArray->Get(i));
332 // Insert enum objects
333 nCount = pParser->rEnumArray->Count();
334 for (i = 0; i < nCount; i++)
335 p->AddEnum((SbxObject *)pParser->rEnumArray->Get(i));
337 if( !p->IsError() )
338 rMod.pImage = p;
339 else
340 delete p;
342 rMod.EndDefinitions();
345 template < class T >
346 class PCodeVisitor
348 public:
349 virtual ~PCodeVisitor();
351 virtual void start( BYTE* pStart ) = 0;
352 virtual void processOpCode0( SbiOpcode eOp ) = 0;
353 virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) = 0;
354 virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) = 0;
355 virtual bool processParams() = 0;
356 virtual void end() = 0;
359 template <class T> PCodeVisitor< T >::~PCodeVisitor()
362 template <class T>
363 class PCodeBufferWalker
365 private:
366 T m_nBytes;
367 BYTE* m_pCode;
368 T readParam( BYTE*& pCode )
370 short nBytes = sizeof( T );
371 T nOp1=0;
372 for ( int i=0; i<nBytes; ++i )
373 nOp1 |= *pCode++ << ( i * 8);
374 return nOp1;
376 public:
377 PCodeBufferWalker( BYTE* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode )
380 void visitBuffer( PCodeVisitor< T >& visitor )
382 BYTE* pCode = m_pCode;
383 if ( !pCode )
384 return;
385 BYTE* pEnd = pCode + m_nBytes;
386 visitor.start( m_pCode );
387 T nOp1 = 0, nOp2 = 0;
388 for( ; pCode < pEnd; )
390 SbiOpcode eOp = (SbiOpcode)(*pCode++);
392 if ( eOp <= SbOP0_END )
393 visitor.processOpCode0( eOp );
394 else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
396 if ( visitor.processParams() )
397 nOp1 = readParam( pCode );
398 else
399 pCode += sizeof( T );
400 visitor.processOpCode1( eOp, nOp1 );
402 else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
404 if ( visitor.processParams() )
406 nOp1 = readParam( pCode );
407 nOp2 = readParam( pCode );
409 else
410 pCode += ( sizeof( T ) * 2 );
411 visitor.processOpCode2( eOp, nOp1, nOp2 );
414 visitor.end();
418 template < class T, class S >
419 class OffSetAccumulator : public PCodeVisitor< T >
421 T m_nNumOp0;
422 T m_nNumSingleParams;
423 T m_nNumDoubleParams;
424 public:
426 OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
427 virtual void start( BYTE* /*pStart*/ ){}
428 virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; }
429 virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){ ++m_nNumSingleParams; }
430 virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; }
431 virtual void end(){}
432 S offset()
434 T result = 0 ;
435 static const S max = std::numeric_limits< S >::max();
436 result = m_nNumOp0 + ( ( sizeof(S) + 1 ) * m_nNumSingleParams ) + ( (( sizeof(S) * 2 )+ 1 ) * m_nNumDoubleParams );
437 if ( result > max )
438 return max;
440 return static_cast<S>(result);
442 virtual bool processParams(){ return false; }
447 template < class T, class S >
449 class BufferTransformer : public PCodeVisitor< T >
451 BYTE* m_pStart;
452 SbiBuffer m_ConvertedBuf;
453 public:
454 BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {}
455 virtual void start( BYTE* pStart ){ m_pStart = pStart; }
456 virtual void processOpCode0( SbiOpcode eOp )
458 m_ConvertedBuf += (UINT8)eOp;
460 virtual void processOpCode1( SbiOpcode eOp, T nOp1 )
462 m_ConvertedBuf += (UINT8)eOp;
463 switch( eOp )
465 case _JUMP:
466 case _JUMPT:
467 case _JUMPF:
468 case _GOSUB:
469 case _CASEIS:
470 case _RETURN:
471 case _ERRHDL:
472 case _TESTFOR:
473 nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
474 break;
475 case _RESUME:
476 if ( nOp1 > 1 )
477 nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
478 break;
479 default:
480 break; //
483 m_ConvertedBuf += (S)nOp1;
485 virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 )
487 m_ConvertedBuf += (UINT8)eOp;
488 if ( eOp == _CASEIS )
489 if ( nOp1 )
490 nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
491 m_ConvertedBuf += (S)nOp1;
492 m_ConvertedBuf += (S)nOp2;
495 virtual bool processParams(){ return true; }
496 virtual void end() {}
497 // yeuch, careful here, you can only call
498 // GetBuffer on the returned SbiBuffer once, also
499 // you (as the caller) get to own the memory
500 SbiBuffer& buffer()
502 return m_ConvertedBuf;
504 static S convertBufferOffSet( BYTE* pStart, T nOp1 )
506 PCodeBufferWalker< T > aBuff( pStart, nOp1);
507 OffSetAccumulator< T, S > aVisitor;
508 aBuff.visitBuffer( aVisitor );
509 return aVisitor.offset();
513 UINT32
514 SbiCodeGen::calcNewOffSet( BYTE* pCode, UINT16 nOffset )
516 return BufferTransformer< UINT16, UINT32 >::convertBufferOffSet( pCode, nOffset );
519 UINT16
520 SbiCodeGen::calcLegacyOffSet( BYTE* pCode, UINT32 nOffset )
522 return BufferTransformer< UINT32, UINT16 >::convertBufferOffSet( pCode, nOffset );
525 template <class T, class S>
526 void
527 PCodeBuffConvertor<T,S>::convert()
529 PCodeBufferWalker< T > aBuf( m_pStart, m_nSize );
530 BufferTransformer< T, S > aTrnsfrmer;
531 aBuf.visitBuffer( aTrnsfrmer );
532 m_pCnvtdBuf = (BYTE*)aTrnsfrmer.buffer().GetBuffer();
533 m_nCnvtdSize = static_cast<S>( aTrnsfrmer.buffer().GetSize() );
536 template class PCodeBuffConvertor< UINT16, UINT32 >;
537 template class PCodeBuffConvertor< UINT32, UINT16 >;