[DICE] Compilation error with two flexpages
Hi everybody, I am currently playing with flexpages. I have written simple client/server application which sends data to each other using flexpages. I have written a simple IDL file for the server interface. The first version was the following : library test_server { interface worker { int send_data([in] flexpage page, [out, max_is(4096)] char reply[]); }; }; The client sends data through the flexpage, and the server replies using string ipc. This way the DICE generated code compiles without error, and my application works. Then I wanted the server to reply also through a flexpage, but another one than the page provided by the client application. So I modify my IDL this way : library test_server { interface worker { int send_data([in] flexpage page, [out, in] flexpage reply); }; }; I use [out, in] because this way the client can first assign the snd_base before sending the request. After modifying my client lib and the component function accordingly, I get a compile error in a DICE generated file : /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c: In function `test_server_worker_wait_any': /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:91: error: `_dice_tmp_offset' undeclared (first use in this function) /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:91: error: (Each undeclared identifier is reported only once /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:91: error: for each function it appears in.) /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c: In function `test_server_worker_reply_and_wait': /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:172: error: `_dice_tmp_offset' undeclared (first use in this function) What I see in the generated file : filter_server_worker_wait_any (...) { ... if (l4_ipc_fpage_received(_dice_result)) { _dice_tmp_offset = 0; while ((_dice_msg_buffer->_word._word[0][_dice_tmp_offset++] != 0) && (_dice_msg_buffer->_word._word[0][_dice_tmp_offset++] != 0)) /* empty */; /* skip zero fpage */ _dice_tmp_offset += 2; _dice_opcode = _dice_msg_buffer->_word._word[0]; } else _dice_opcode = _dice_msg_buffer->_word._word[0]; return _dice_opcode; } The _dice_tmp_offset is not declared, the second error (line 172) is about the same thing (it is exactly the same code in reply_and_wait()). So I have tried to declare _dice_tmp_offset as an unsigned int, then I have : /home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_ worker-server.c: In function `filter_server_worker_wait_any': /home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_ worker-server.c:92: error: subscripted value is neither array nor pointer /home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_ worker-server.c:92: error: subscripted value is neither array nor pointer (The line 92 is the one with while(...)). Indeed after looking the code I find it really strange, as _word[0] is a register.... More _dice_tmp_offset is incremented by two after the while loop and never used after... I really don't understand this code... If I only set the reply flexpage as [in], I have the same behavior... Am I doing something wrong ? Could it be a bug in DICE ? Is it permitted to use one in-flexpage and one out-flexpage for the same function ? Is there something special to do ? Thanks, -- nico
Clermont, Nicolas wrote on 08/01/2007 02:49 PM this:
Hi everybody,
I am currently playing with flexpages. I have written simple client/server application which sends data to each other using flexpages. I have written a simple IDL file for the server interface. The first version was the following :
library test_server { interface worker { int send_data([in] flexpage page, [out, max_is(4096)] char reply[]); }; };
The client sends data through the flexpage, and the server replies using string ipc. This way the DICE generated code compiles without error, and my application works. Then I wanted the server to reply also through a flexpage, but another one than the page provided by the client application. So I modify my IDL this way :
library test_server { interface worker { int send_data([in] flexpage page, [out, in] flexpage reply); }; };
I use [out, in] because this way the client can first assign the snd_base before sending the request. Note, that the "reply" parameter will be sent as a flexpage to the server, that is, the page described by "reply" will be mapped. If you just want to tell the server the send-base it should use, write smething like this:
int send_data([in] flexpage page, [in] unsigned long send_base, [out] flexpage *reply);
After modifying my client lib and the component function accordingly, I get a compile error in a DICE generated file : /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c: In function `test_server_worker_wait_any': /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:91: error: `_dice_tmp_offset' undeclared (first use in this function) /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:91: error: (Each undeclared identifier is reported only once /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:91: error: for each function it appears in.) /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c: In function `test_server_worker_reply_and_wait': /home/nico/build-tudos/pkg/test_server/idl/OBJ-x86-l4v2/test_server_worker-s erver.c:172: error: `_dice_tmp_offset' undeclared (first use in this function)
What I see in the generated file :
filter_server_worker_wait_any (...) { ... if (l4_ipc_fpage_received(_dice_result)) { _dice_tmp_offset = 0; while ((_dice_msg_buffer->_word._word[0][_dice_tmp_offset++] != 0) && (_dice_msg_buffer->_word._word[0][_dice_tmp_offset++] != 0)) /* empty */; /* skip zero fpage */ _dice_tmp_offset += 2; _dice_opcode = _dice_msg_buffer->_word._word[0]; } else _dice_opcode = _dice_msg_buffer->_word._word[0]; return _dice_opcode; }
The _dice_tmp_offset is not declared, the second error (line 172) is about the same thing (it is exactly the same code in reply_and_wait()). So I have tried to declare _dice_tmp_offset as an unsigned int, then I have : /home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_ worker-server.c: In function `filter_server_worker_wait_any': /home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_ worker-server.c:92: error: subscripted value is neither array nor pointer /home/clermont/build-tudos/pkg/filter_server/idl/OBJ-x86-l4v2/filter_server_ worker-server.c:92: error: subscripted value is neither array nor pointer
(The line 92 is the one with while(...)). Indeed after looking the code I find it really strange, as _word[0] is a register.... More _dice_tmp_offset is incremented by two after the while loop and never used after... I really don't understand this code...
If I only set the reply flexpage as [in], I have the same behavior...
Am I doing something wrong ? No.
Could it be a bug in DICE ? Yes. Fix attached. Should be in public repository tomorrow.
Is it permitted to use one in-flexpage and one out-flexpage for the same function ? Yes.
Is there something special to do ? If you want to receive a flexpage from the server, you will have to set the IPC flexpage receive window in the client. The Dice generated code uses the rcv_fpage member in the CORBA_Environment parameter of the *_call functions to do this. Thus, you have to set this member appropriately. Per default this member is set to L4_WHOLE_ADDRESS_SPACE (dice_default_environment).
Thanks for the bug-report, Ron. -- Mit freundlichen Gruessen / with regards ra3 @ inf.tu-dresden.de http://os.inf.tu-dresden.de/~ra3/ Index: be/BEMsgBuffer.cpp =================================================================== --- be/BEMsgBuffer.cpp (revision 29459) +++ be/BEMsgBuffer.cpp (working copy) @@ -1176,6 +1176,42 @@ CBEMsgBuffer::WriteMemberAccess(CBEFile& } } +/** \brief writes the access to a member of a specific type + * \param pFile the file to write to + * \param pFunction the function to write the member for + * \param nType the type of the message buffer struct + * \param nFEType the type of the member + * \param sIndex the string used as index into the array, not used if empty + * + * First we look for the specific member and then call the WriteAccess method + * with the member. + */ +void +CBEMsgBuffer::WriteMemberAccess(CBEFile& pFile, + CBEFunction *pFunction, + CMsgStructType nType, + int nFEType, + string sIndex) +{ + // get struct + CBEStructType *pStruct = GetStruct(pFunction, nType); + assert(pStruct); + // iterate members and count to the wanted type (remember: 0-based) + vector<CBETypedDeclarator*>::iterator iter; + for (iter = pStruct->m_Members.begin(); + iter != pStruct->m_Members.end(); + iter++) + { + if ((*iter)->GetType()->GetFEType() != nFEType) + continue; + + WriteAccess(pFile, pFunction, nType, *iter); + if (!sIndex.empty()) + pFile << "[" << sIndex << "]"; + return; + } +} + /** \brief write the access to a member of the generic struct * \param pFile the file to write to * \param nIndex the index into the word array of the generic struct Index: be/l4/L4BEWaitAnyFunction.cpp =================================================================== --- be/l4/L4BEWaitAnyFunction.cpp (revision 29459) +++ be/l4/L4BEWaitAnyFunction.cpp (working copy) @@ -78,6 +78,16 @@ CL4BEWaitAnyFunction::CreateBackEnd(CFEI string sCurr = sResult; AddLocalVariable(sDope, sResult, 0, string("{ msgdope: 0 }")); + + // if we have flexible number of flexpages, we need a temporary variable + bool bFixedNumberOfFlexpages = true; + m_pClass->GetParameterCount(TYPE_FLEXPAGE, bFixedNumberOfFlexpages, DIRECTION_INOUT); + if (!bFixedNumberOfFlexpages) + { + string sTempVar = pNF->GetTempOffsetVariable(); + string sTempType = pNF->GetTypeName(TYPE_MWORD, false); + AddLocalVariable(sTempType, sTempVar, 0); + } } /** \brief initializes the variables @@ -561,14 +571,14 @@ void CL4BEWaitAnyFunction::WriteFlexpage CBESizes *pSizes = CCompiler::GetSizes(); int nSizeFpage = pSizes->GetSizeOfType(TYPE_FLEXPAGE) / pSizes->GetSizeOfType(TYPE_MWORD); + CBETypedDeclarator *pReturn = GetReturnVariable(); + if (!pReturn) + return; // if fixed number (should be true for only one flexpage as well) if (bFixedNumberOfFlexpages) { // the fixed offset (where to find the opcode) is: // offset = 8*nMaxNumberOfFlexpages + 8 - CBETypedDeclarator *pReturn = GetReturnVariable(); - if (!pReturn) - return; CL4BEMarshaller *pMarshaller = dynamic_cast<CL4BEMarshaller*>(GetMarshaller()); assert(pMarshaller); @@ -588,10 +598,10 @@ void CL4BEWaitAnyFunction::WriteFlexpage // init temp var ++pFile << "\t" << sTempVar << " = 0;\n"; pFile << "\twhile (("; - pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, 0); - pFile << "[" << sTempVar << "++] != 0) && ("; - pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, 0); - pFile << "[" << sTempVar << "++] != 0)) /* empty */;\n"; + pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, sTempVar); + pFile << " != 0) && ("; + pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, sTempVar + "+1"); + pFile << " != 0)) " << sTempVar << " += 2;\n"; // now sTempVar points to the delimiter flexpage // we have to add another 8 bytes to find the opcode, because @@ -599,7 +609,9 @@ void CL4BEWaitAnyFunction::WriteFlexpage pFile << "\t/* skip zero fpage */\n"; pFile << "\t" << sTempVar << " += 2;\n"; // now unmarshal opcode - WriteMarshalReturn(pFile, false); + pFile << "\t" << pReturn->m_Declarators.First()->GetName() << " = "; + pMsgBuffer->WriteMemberAccess(pFile, this, CMsgStructType::Generic, TYPE_MWORD, sTempVar); + pFile << ";\n"; --pFile << "\t}\n"; } } Index: be/BEClass.cpp =================================================================== --- be/BEClass.cpp (revision 29459) +++ be/BEClass.cpp (working copy) @@ -881,26 +881,35 @@ CBEClass::GetParameterCount(int nFEType, bool& bSameCount, DIRECTION_TYPE nDirection) { - if (nDirection == 0) + if (nDirection == DIRECTION_INOUT) { // count both and return max int nCountIn = GetParameterCount(nFEType, bSameCount, DIRECTION_IN); int nCountOut = GetParameterCount(nFEType, bSameCount, DIRECTION_OUT); - return (nCountIn > nCountOut) ? nCountIn : nCountOut; + return std::max(nCountIn, nCountOut); } int nCount = 0, nCurr; + CCompiler::Verbose(PROGRAM_VERBOSE_DEBUG, + "%s(%d, %s, %d) called: max is %d\n", __func__, + nFEType, bSameCount ? "true" : "false", nDirection, nCount); vector<CBEFunction*>::iterator iter; for (iter = m_Functions.begin(); iter != m_Functions.end(); iter++) { - nCurr = (*iter)->GetParameterCount(nFEType, nDirection); - if ((nCount > 0) && (nCurr != nCount) && (nCurr > 0)) - bSameCount = false; - if (nCurr > nCount) nCount = nCurr; + nCurr = (*iter)->GetParameterCount(nFEType, nDirection); + CCompiler::Verbose(PROGRAM_VERBOSE_DEBUG, + "%s: checking %s: has %d parameter of type %d, max is %d\n", __func__, + (*iter)->GetName().c_str(), nCurr, nFEType, nCount); + if ((nCount > 0) && (nCurr != nCount) && (nCurr > 0)) + bSameCount = false; + nCount = std::max(nCurr, nCount); } + CCompiler::Verbose(PROGRAM_VERBOSE_DEBUG, + "%s: returns %d (same %s)\n", __func__, + nCount, bSameCount ? "true" : "false"); return nCount; } @@ -915,7 +924,7 @@ CBEClass::GetStringParameterCount(DIRECT ATTR_TYPE nMustAttrs, ATTR_TYPE nMustNotAttrs) { - if (nDirection == 0) + if (nDirection == DIRECTION_INOUT) { int nStringsIn = GetStringParameterCount(DIRECTION_IN, nMustAttrs, nMustNotAttrs); @@ -953,7 +962,7 @@ CBEClass::GetStringParameterCount(DIRECT */ int CBEClass::GetSize(DIRECTION_TYPE nDirection) { - if (nDirection == 0) + if (nDirection == DIRECTION_INOUT) { int nSizeIn = GetSize(DIRECTION_IN); int nSizeOut = GetSize(DIRECTION_OUT); @@ -2349,7 +2358,7 @@ CBEClass::GetParameterCount(ATTR_TYPE nM ATTR_TYPE nMustNotAttrs, DIRECTION_TYPE nDirection) { - if (nDirection == 0) + if (nDirection == DIRECTION_INOUT) { int nCountIn = GetParameterCount(nMustAttrs, nMustNotAttrs, DIRECTION_IN); Index: be/BEFunction.cpp =================================================================== --- be/BEFunction.cpp (revision 29459) +++ be/BEFunction.cpp (working copy) @@ -1609,7 +1609,7 @@ CBEFunction::HasVariableSizedParameters( */ int CBEFunction::GetParameterCount(int nFEType, DIRECTION_TYPE nDirection) { - if (nDirection == 0) + if (nDirection == DIRECTION_INOUT) { int nCountIn = GetParameterCount(nFEType, DIRECTION_IN); int nCountOut = GetParameterCount(nFEType, DIRECTION_OUT); @@ -1630,8 +1630,22 @@ int CBEFunction::GetParameterCount(int n pType = (*iter)->GetType(); if ((pAttr = (*iter)->m_Attributes.Find(ATTR_TRANSMIT_AS)) != 0) pType = pAttr->GetAttrType(); - if (pType->IsOfType(nFEType)) - nCount++; + if (!pType->IsOfType(nFEType)) + continue; + + // to catch array parameters, we have to get the maximum size and + // divide by the size of the type + int nParamSize = 0; + CBESizes *pSizes = CCompiler::GetSizes(); + int nTypeSize = pSizes->GetSizeOfType(nFEType); + if ((*iter)->GetMaxSize(nParamSize)) + nParamSize /= nTypeSize; + else + nParamSize = 1; // it's variable size, so count it at least once + if (nParamSize > 0) + nCount += nParamSize; + else + nCount++; } return nCount; @@ -1648,7 +1662,7 @@ CBEFunction::GetParameterCount(ATTR_TYPE ATTR_TYPE nMustNotAttrs, DIRECTION_TYPE nDirection) { - if (nDirection == 0) + if (nDirection == DIRECTION_INOUT) { int nCountIn = GetParameterCount(nMustAttrs, nMustNotAttrs, DIRECTION_IN); Index: be/BEMsgBuffer.h =================================================================== --- be/BEMsgBuffer.h (revision 29459) +++ be/BEMsgBuffer.h (working copy) @@ -80,6 +80,8 @@ public: // public methods CMsgStructType nType, CDeclStack* pStack); virtual void WriteMemberAccess(CBEFile& pFile, CBEFunction *pFunction, CMsgStructType nType, int nFEType, int nIndex); + virtual void WriteMemberAccess(CBEFile& pFile, CBEFunction *pFunction, + CMsgStructType nType, int nFEType, string sIndex); virtual void WriteGenericMemberAccess(CBEFile& pFile, int nIndex); void WriteAccessToStruct(CBEFile& pFile, CBEFunction *pFunction, CMsgStructType nType);
participants (2)
-
Clermont, Nicolas -
Ronald Aigner