CalcAssembler.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calculator/CalcAssembler.cpp#3 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "fennel/common/CommonPreamble.h"
00024 #include "fennel/calculator/InstructionCommon.h"
00025 #include "fennel/calculator/CalcAssembler.h"
00026 
00027 #include <strstream>
00028 #include "boost/cast.hpp"
00029 
00030 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/calculator/CalcAssembler.cpp#3 $");
00031 
00032 using namespace std;
00033 
00034 CalcAssembler::~CalcAssembler()
00035 {
00036     for (uint i = RegisterReference::EFirstSet;
00037          i < RegisterReference::ELastSet;
00038          i++)
00039     {
00040         if (mCalc->mRegisterSetBinding[i] == NULL) {
00041             // We did NOT successfully bind this register set to the calculator
00042             // Will need to delete it on our own
00043             if (mBuffers[i]) {
00044                 delete[] mBuffers[i];
00045             }
00046             if (mRegisterTupleData[i]) {
00047                 delete mRegisterTupleData[i];
00048             }
00049         }
00050     }
00051 }
00052 
00053 void CalcAssembler::init()
00054 {
00055     mCurrentRegSet = RegisterReference::EUnknown;
00056     mLiteralIndex  = 0;
00057     mMaxPC         = 0;
00058 
00059     /* Initialize tuple descriptors and tuple data */
00060     for (uint i = RegisterReference::EFirstSet;
00061          i < RegisterReference::ELastSet;
00062          i++)
00063     {
00064         mRegisterSetDescriptor[i].clear();
00065         mRegisterTupleData[i] = NULL;
00066         mBuffers[i] = NULL;
00067     }
00068 }
00069 
00070 int CalcAssembler::assemble(const char* program)
00071 {
00072     int res = 0;
00073     istringstream istr(program);
00074     mLexer.switch_streams(&istr, 0);
00075     try {
00076         assemble();
00077     } catch (CalcAssemblerException& ex) {
00078         ex.setCode(program);
00079         throw ex;
00080     }
00081 
00082     return res;
00083 }
00084 
00085 int CalcAssembler::assemble()
00086 {
00087     int res = 0;
00088     try {
00089         mCalc->mIsAssembling = true;
00090         res = CalcYYparse((void*) this);
00091         if (res != 0) {
00092             throw CalcAssemblerException(
00093                 "Error assembling program", getLexer().getLocation());
00094         }
00095 
00096         // Done assembling - let's check the maximum PC (used in Jump
00097         // instruction)
00098         checkPC(mMaxPC, mMaxPCLoc);
00099     } catch (CalcAssemblerException& ex) {
00100         if (!ex.mLocValid) {
00101             ex.setLocation(getLexer().getLocation());
00102         }
00103         throw ex;
00104     } catch (FennelExcn& ex) {
00105         throw CalcAssemblerException(ex.getMessage(), getLexer().getLocation());
00106     } catch (std::exception& ex) {
00107         throw CalcAssemblerException(ex.what(), getLexer().getLocation());
00108     }
00109 
00110     return res;
00111 }
00112 
00113 void CalcAssembler::setTupleDatum(
00114     StandardTypeDescriptorOrdinal type,
00115     TupleDatum& tupleDatum,
00116     TupleAttributeDescriptor& desc /* Unused */,
00117     PConstBuffer buffer)
00118 {
00119     tupleDatum.pData = buffer;
00120 }
00121 
00122 void CalcAssembler::setTupleDatum(
00123     StandardTypeDescriptorOrdinal type,
00124     TupleDatum& tupleDatum,
00125     TupleAttributeDescriptor& desc, /* Unused */
00126     double value)
00127 {
00128     switch (type) {
00129     case STANDARD_TYPE_REAL:
00130 
00131         *(reinterpret_cast<float *>(const_cast<PBuffer>(tupleDatum.pData))) =
00132             boost::numeric_cast<float>(value);
00133 
00134         // Check for underflow where the value becomes 0
00135         // NOTE: Underflows that causes precision loss but does not become 0
00136         //       are ignored for now.
00137         if ((value != 0) &&
00138             (*(reinterpret_cast<float *>(const_cast<PBuffer>(tupleDatum.pData)))
00139              == 0))
00140         {
00141             throw InvalidValueException<double>(
00142                 "bad numeric cast: underflow", type, value);
00143         }
00144         break;
00145     case STANDARD_TYPE_DOUBLE:
00146         *(reinterpret_cast<double *>(const_cast<PBuffer>(tupleDatum.pData))) =
00147             boost::numeric_cast<double>(value);
00148         break;
00149     default:
00150         // Invalid real type - horrible, horrible
00151         throw InvalidValueException<double>(
00152             "Cannot assign double", type, value);
00153     }
00154 }
00155 
00156 void CalcAssembler::setTupleDatum(
00157     StandardTypeDescriptorOrdinal type,
00158     TupleDatum& tupleDatum,
00159     TupleAttributeDescriptor& desc, /* Unused */
00160     uint64_t value)
00161 {
00162     switch (type) {
00163     case STANDARD_TYPE_INT_8:
00164         *(reinterpret_cast<int8_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00165             boost::numeric_cast<int8_t>(value);
00166         break;
00167     case STANDARD_TYPE_UINT_8:
00168         *(reinterpret_cast<uint8_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00169             boost::numeric_cast<uint8_t>(value);
00170         break;
00171     case STANDARD_TYPE_INT_16:
00172         *(reinterpret_cast<int16_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00173                 boost::numeric_cast<int16_t>(value);
00174         break;
00175     case STANDARD_TYPE_UINT_16:
00176         *(reinterpret_cast<uint16_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00177             boost::numeric_cast<uint16_t>(value);
00178         break;
00179     case STANDARD_TYPE_INT_32:
00180         *(reinterpret_cast<int32_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00181             boost::numeric_cast<int32_t>(value);
00182         break;
00183     case STANDARD_TYPE_UINT_32:
00184         *(reinterpret_cast<uint32_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00185             boost::numeric_cast<uint32_t>(value);
00186         break;
00187     case STANDARD_TYPE_INT_64:
00188         // Explicitly check for overflow of int64_t because the boost
00189         // boost::numeric_cast does not throw an exception in this case
00190         if (value > std::numeric_limits<int64_t>::max()) {
00191             throw InvalidValueException<uint64_t>(
00192                 "bad numeric cast: overflow", type, value);
00193         }
00194         *(reinterpret_cast<int64_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00195             boost::numeric_cast<int64_t>(value);
00196         break;
00197     case STANDARD_TYPE_UINT_64:
00198         *(reinterpret_cast<uint64_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00199             boost::numeric_cast<uint64_t>(value);
00200             break;
00201     case STANDARD_TYPE_BOOL:
00202         // Booleans are specifed as 0 or 1
00203         if (value == 1) {
00204             *(reinterpret_cast<bool *>(const_cast<PBuffer>(tupleDatum.pData))) =
00205                 true;
00206         } else if (value == 0) {
00207             *(reinterpret_cast<bool *>(const_cast<PBuffer>(tupleDatum.pData))) =
00208                 false;
00209         } else {
00210             // Invalid boolean value
00211             throw InvalidValueException<uint64_t>(
00212                 "Boolean value should be 0 or 1", type, value);
00213         }
00214         break;
00215     default:
00216         // Invalid unsigned integer type - horrible, horrible
00217         throw InvalidValueException<uint64_t>(
00218             "Cannot assign unsigned integer", type, value);
00219     }
00220 }
00221 
00222 void CalcAssembler::setTupleDatum(
00223     StandardTypeDescriptorOrdinal type,
00224     TupleDatum& tupleDatum,
00225     TupleAttributeDescriptor& desc, /* Unused */
00226     int64_t value)
00227 {
00228     switch (type) {
00229     case STANDARD_TYPE_INT_8:
00230         *(reinterpret_cast<int8_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00231             boost::numeric_cast<int8_t>(value);
00232         break;
00233     case STANDARD_TYPE_INT_16:
00234         *(reinterpret_cast<int16_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00235             boost::numeric_cast<int16_t>(value);
00236         break;
00237     case STANDARD_TYPE_INT_32:
00238         *(reinterpret_cast<int32_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00239             boost::numeric_cast<int32_t>(value);
00240         break;
00241     case STANDARD_TYPE_INT_64:
00242         *(reinterpret_cast<int64_t *>(const_cast<PBuffer>(tupleDatum.pData))) =
00243             boost::numeric_cast<int64_t>(value);
00244         break;
00245     default:
00246         throw InvalidValueException<int64_t>(
00247             "Cannot assign signed integer", type, value);
00248     }
00249 }
00250 
00251 void CalcAssembler::setTupleDatum(
00252     StandardTypeDescriptorOrdinal type,
00253     TupleDatum& tupleDatum,
00254     TupleAttributeDescriptor& desc,
00255     string str)
00256 {
00257     ostringstream errorStr;
00258     char* ptr = reinterpret_cast<char*>(const_cast<PBuffer>(tupleDatum.pData));
00259     switch (type) {
00260     case STANDARD_TYPE_CHAR:
00261     case STANDARD_TYPE_BINARY:
00262         // Fixed length storage
00263         // For fixed length arrays, cbData should be the same as cbStorage
00264         assert(tupleDatum.cbData == desc.cbStorage);
00265 
00266         // Fixed width arrays should be padded to be the specifed width
00267         // Verify that the number of bytes matches the specified width
00268         if (str.length() != tupleDatum.cbData) {
00269             ostringstream ostr("");
00270             ostr << "String length " << str.length()
00271                  << " not equal to fixed size array of length "
00272                  << tupleDatum.cbData;
00273             throw FennelExcn(ostr.str());
00274         }
00275 
00276         // Copy the string
00277         memcpy(ptr, str.data(), str.length());
00278         break;
00279 
00280     case STANDARD_TYPE_VARCHAR:
00281     case STANDARD_TYPE_VARBINARY:
00282         // Variable length storage
00283 
00284         // Verify that there the length of the string is not larger than the
00285         // maximum length
00286         if (str.length() > desc.cbStorage) {
00287             ostringstream ostr("");
00288             ostr << "String length " << str.length()
00289                  << " too long for variabled sized array of maximum length "
00290                  << desc.cbStorage;
00291             throw FennelExcn(ostr.str());
00292         }
00293 
00294         // Copy the string
00295         memcpy(ptr, str.data(), str.length());
00296         tupleDatum.cbData = str.length();
00297         break;
00298 
00299     default:
00300         throw InvalidValueException<string>("Cannot assign string", type, str);
00301     }
00302 }
00303 
00304 void CalcAssembler::bindLiteralDone()
00305 {
00306     // We are done with binding literals
00307     // Check that all literals have been a value
00308     TRegisterIndex regSize = getRegisterSize(RegisterReference::ELiteral);
00309     if (mLiteralIndex != regSize) {
00310         ostringstream errorStr("");
00311         errorStr << "Error binding literals: " << regSize
00312                  << " literal registers, only " << mLiteralIndex
00313                  << " registers bound";
00314         throw CalcAssemblerException(errorStr.str(), getLexer().getLocation());
00315     }
00316 }
00317 
00318 void CalcAssembler::selectRegisterSet(RegisterReference::ERegisterSet setIndex)
00319 {
00320     mCurrentRegSet = setIndex;
00321 }
00322 
00323 StandardTypeDescriptorOrdinal CalcAssembler::getRegisterType(
00324     RegisterReference::ERegisterSet setIndex,
00325     TRegisterIndex regIndex)
00326 {
00327     RegisterReference* regRef = getRegister(setIndex, regIndex);
00328     assert(regRef != NULL);
00329     return regRef->type();
00330 }
00331 
00332 RegisterReference* CalcAssembler::getRegister(
00333     RegisterReference::ERegisterSet setIndex,
00334     TRegisterIndex regIndex)
00335 {
00336     assert(setIndex < RegisterReference::ELastSet);
00337     TRegisterIndex size = getRegisterSize(setIndex);
00338     if (regIndex >= size) {
00339         ostringstream errorStr("");
00340         errorStr << "Register index " << regIndex << " out of bounds.";
00341         errorStr << " Register set " << RegisterReference::getSetName(setIndex)
00342                  << " has " << size << " registers.";
00343         throw CalcAssemblerException(errorStr.str(), getLexer().getLocation());
00344     }
00345     return mCalc->mRegisterRef[setIndex][regIndex];
00346 }
00347 
00348 TRegisterIndex CalcAssembler::getRegisterSize(
00349     RegisterReference::ERegisterSet setIndex)
00350 {
00351     assert(setIndex < RegisterReference::ELastSet);
00352     return mCalc->mRegisterRef[setIndex].size();
00353 }
00354 
00355 TupleData* CalcAssembler::getTupleData(RegisterReference::ERegisterSet setIndex)
00356 {
00357     assert(setIndex < RegisterReference::ELastSet);
00358     return mRegisterTupleData[setIndex];
00359 }
00360 
00361 TupleDescriptor& CalcAssembler::getTupleDescriptor(
00362     RegisterReference::ERegisterSet setIndex)
00363 {
00364     assert(setIndex < RegisterReference::ELastSet);
00365     return mRegisterSetDescriptor[setIndex];
00366 }
00367 
00368 /* Need factory? */
00369 RegisterReference* CalcAssembler::createRegisterReference(
00370     RegisterReference::ERegisterSet setIndex,
00371     TRegisterIndex                  regIndex,
00372     StandardTypeDescriptorOrdinal   regType)
00373 {
00374     // TODO: check setIndex and regIndex
00375     RegisterReference* regRef = NULL;
00376     switch (regType) {
00377     case STANDARD_TYPE_INT_8:
00378         regRef = new RegisterRef<int8_t>(setIndex, regIndex, regType);
00379         break;
00380     case STANDARD_TYPE_UINT_8:
00381         regRef = new RegisterRef<uint8_t>(setIndex, regIndex, regType);
00382         break;
00383     case STANDARD_TYPE_INT_16:
00384         regRef = new RegisterRef<int16_t>(setIndex, regIndex, regType);
00385         break;
00386     case STANDARD_TYPE_UINT_16:
00387         regRef = new RegisterRef<uint16_t>(setIndex, regIndex, regType);
00388         break;
00389     case STANDARD_TYPE_INT_32:
00390         regRef = new RegisterRef<int32_t>(setIndex, regIndex, regType);
00391         break;
00392     case STANDARD_TYPE_UINT_32:
00393         regRef = new RegisterRef<uint32_t>(setIndex, regIndex, regType);
00394         break;
00395     case STANDARD_TYPE_INT_64:
00396         regRef = new RegisterRef<int64_t>(setIndex, regIndex, regType);
00397         break;
00398     case STANDARD_TYPE_UINT_64:
00399         regRef = new RegisterRef<uint64_t>(setIndex, regIndex, regType);
00400         break;
00401     case STANDARD_TYPE_REAL:
00402         regRef = new RegisterRef<float>(setIndex, regIndex, regType);
00403         break;
00404     case STANDARD_TYPE_DOUBLE:
00405         regRef = new RegisterRef<double>(setIndex, regIndex, regType);
00406         break;
00407     case STANDARD_TYPE_BOOL:
00408         regRef = new RegisterRef<bool>(setIndex, regIndex, regType);
00409         break;
00410     case STANDARD_TYPE_CHAR:
00411     case STANDARD_TYPE_VARCHAR:
00412         regRef = new RegisterRef<char*>(setIndex, regIndex, regType);
00413         break;
00414     case STANDARD_TYPE_BINARY:
00415     case STANDARD_TYPE_VARBINARY:
00416         regRef = new RegisterRef<int8_t*>(setIndex, regIndex, regType);
00417         break;
00418     default:
00419         ostringstream errorStr("");
00420         errorStr << "Error creating register reference for "
00421                  << RegisterReference::toString(setIndex, regIndex) << ": ";
00422         errorStr << "Unsupported register type " << regType;
00423         throw CalcAssemblerException(errorStr.str());
00424         break;
00425     }
00426     return regRef;
00427 }
00428 
00429 void CalcAssembler::addRegister(
00430     RegisterReference::ERegisterSet setIndex,
00431     StandardTypeDescriptorOrdinal   regType,
00432     TupleStorageByteLength          cbStorage)
00433 {
00434     assert(mCurrentRegSet < RegisterReference::ELastSet);
00435     bool isNullable = true;
00436 
00437     /* Add to tuple descriptor */
00438     StoredTypeDescriptor const &typeDesc = mTypeFactory.newDataType(regType);
00439     getTupleDescriptor(mCurrentRegSet).push_back(
00440         TupleAttributeDescriptor(typeDesc, isNullable, cbStorage));
00441 
00442     /* Add register to calculator */
00443     TRegisterIndex regIndex = mCalc->mRegisterRef[setIndex].size();
00444     RegisterReference* regRef =
00445         createRegisterReference(setIndex, regIndex, regType);
00446     mCalc->appendRegRef(regRef);
00447 }
00448 
00449 void CalcAssembler::addRegister(
00450     StandardTypeDescriptorOrdinal const regType,
00451     TupleStorageByteLength cbStorage)
00452 {
00453     addRegister(mCurrentRegSet, regType, cbStorage);
00454 }
00455 
00456 TupleData* CalcAssembler::createTupleData(
00457     TupleDescriptor const& tupleDesc,
00458     FixedBuffer** buf)
00459 {
00460     assert(buf != NULL);
00461 
00462     /* Prepare tuples - should only do this for literal/local */
00463     /* Compute memory layout and access */
00464     TupleAccessor tupleAccessor;
00465     tupleAccessor.compute(tupleDesc, TUPLE_FORMAT_ALL_FIXED);
00466 
00467     int maxByteCount = tupleAccessor.getMaxByteCount();
00468 
00469     /* Allocate memory */
00470     *buf = new FixedBuffer[maxByteCount];
00471 
00472     /* Zero the memory. */
00473     memset(*buf, 0, maxByteCount);
00474 
00475     /* Link memory - Who will delete this????? */
00476     tupleAccessor.setCurrentTupleBuf(*buf, false);
00477 
00478     /* Create Tuple Data - to be deleted by the calculator */
00479     TupleData* pTupleData = new TupleData(tupleDesc);
00480 
00481     /* Link Tuple Data with Tuple Accessor memory */
00482     tupleAccessor.unmarshal(*pTupleData);
00483     return pTupleData;
00484 }
00485 
00486 
00487 void CalcAssembler::allocateTuples()
00488 {
00489     /* Allocate memory for the tuples */
00490     for (uint reg = RegisterReference::EFirstSet;
00491          reg < RegisterReference::ELastSet;
00492          reg++)
00493     {
00494         /* Verify that tuples have not already been allocated */
00495         assert(mRegisterTupleData[reg] == NULL);
00496         assert(mBuffers[reg] == NULL);
00497 
00498         if (reg == RegisterReference::ELiteral ||
00499             reg == RegisterReference::EStatus ||
00500             reg == RegisterReference::ELocal)
00501         {
00502             /* Allocate tuple for literal/status/local registers */
00503             mRegisterTupleData[reg] = createTupleData(
00504                 mRegisterSetDescriptor[reg],
00505                 &mBuffers[reg]);
00506         }
00507 
00508         /* Do not need to create input/output tuple data */
00509     }
00510 }
00511 
00512 void CalcAssembler::bindRegisters()
00513 {
00514     /* Bind registers to calculator */
00515     RegisterReference::ERegisterSet reg;
00516 
00517     /* Bind literal */
00518     reg = RegisterReference::ELiteral;
00519     mCalc->mBuffers.push_back(mBuffers[reg]);
00520     mCalc->bind(reg, getTupleData(reg), getTupleDescriptor(reg));
00521 
00522     /* Bind status */
00523     reg = RegisterReference::EStatus;
00524     mCalc->mBuffers.push_back(mBuffers[reg]);
00525     mCalc->bind(reg, getTupleData(reg), getTupleDescriptor(reg));
00526 
00527     /* Bind local */
00528     reg = RegisterReference::ELocal;
00529     mCalc->mBuffers.push_back(mBuffers[reg]);
00530     mCalc->bind(reg, getTupleData(reg), getTupleDescriptor(reg));
00531 
00532     /* Do not create input/output tuple data - we still need to bind
00533        the tuple descriptor */
00534     reg = RegisterReference::EInput;
00535     mCalc->mRegisterSetDescriptor[reg] =
00536         new TupleDescriptor(getTupleDescriptor(reg));
00537 
00538     reg = RegisterReference::EOutput;
00539     mCalc->mRegisterSetDescriptor[reg] =
00540         new TupleDescriptor(getTupleDescriptor(reg));
00541 }
00542 
00543 void CalcAssembler::addInstruction(Instruction* inst)
00544 {
00545     assert(inst != NULL);
00546     mCalc->appendInstruction(inst);
00547 }
00548 
00549 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/calculator/CalcAssembler.cpp#3 $");
00550 
00551 // End CalcAssembler.cpp

Generated on Mon Jun 22 04:00:16 2009 for Fennel by  doxygen 1.5.1