00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef Fennel_CalcAssembler_Included
00024 #define Fennel_CalcAssembler_Included
00025
00026 #include "fennel/calculator/CalcLexer.h"
00027 #include "fennel/calculator/CalcAssemblerException.h"
00028 #include "fennel/calculator/InstructionFactory.h"
00029
00030 #include <strstream>
00031
00032 FENNEL_BEGIN_NAMESPACE
00033
00034 using namespace std;
00035
00036 typedef size_t TRegisterIndex;
00037
00038 class Calculator;
00039 class RegisterReference;
00040 class TupleDescriptor;
00041 class StoredTypeDescriptorFactory;
00042
00043 extern int CalcYYparse (void *);
00044
00062 class FENNEL_CALCULATOR_EXPORT CalcAssembler
00063 {
00064 public:
00065 explicit
00066 CalcAssembler(Calculator* calc) {
00067 assert(calc != NULL);
00068 mCalc = calc;
00069 }
00070
00071 ~CalcAssembler();
00072
00073 CalcLexer& getLexer() {
00074 return mLexer;
00075 }
00076
00077 int assemble(const char* program);
00078 int assemble();
00079
00080
00081 static TupleData*
00082 createTupleData(
00083 TupleDescriptor const& tupleDes,
00084 FixedBuffer** buf);
00085
00086 static RegisterReference*
00087 createRegisterReference(
00088 RegisterReference::ERegisterSet setIndex,
00089 TRegisterIndex regIndex,
00090 StandardTypeDescriptorOrdinal regType);
00091
00092 static Instruction*
00093 createInstruction(
00094 string& name,
00095 vector<RegisterReference*> const &operands,
00096 CalcYYLocType& location)
00097 {
00098 Instruction* inst = NULL;
00099 try {
00100 inst = InstructionFactory::createInstruction(name, operands);
00101 } catch (FennelExcn& ex) {
00102 throw CalcAssemblerException(ex.getMessage(), location);
00103 } catch (std::exception& ex) {
00104 throw CalcAssemblerException(ex.what(), location);
00105 }
00106 if (inst == NULL) {
00107 string error;
00108 error = "Error instantiating instruction: " + name;
00109 if (operands.size() > 0) {
00110 error += " ";
00111 int i;
00112 for (i = 0; i < operands.size(); i++) {
00113 error += operands[i]->toString();
00114 if (i + 1 < operands.size()) {
00115 error += ", ";
00116 }
00117 }
00118 }
00119 throw CalcAssemblerException(error, location);
00120 }
00121 return inst;
00122 }
00123
00124 static Instruction* createInstruction(
00125 string& name,
00126 RegisterReference* result,
00127 RegisterReference* operand1,
00128 RegisterReference* operand2,
00129 CalcYYLocType& location)
00130 {
00131 vector<RegisterReference*> operands;
00132 operands.push_back(result);
00133 operands.push_back(operand1);
00134 operands.push_back(operand2);
00135 return createInstruction(name, operands, location);
00136 }
00137
00138
00139 static Instruction* createInstruction(
00140 string& name,
00141 RegisterReference* result,
00142 RegisterReference* operand1,
00143 CalcYYLocType& location)
00144 {
00145 vector<RegisterReference*> operands;
00146 operands.push_back(result);
00147 operands.push_back(operand1);
00148 return createInstruction(name, operands, location);
00149 }
00150
00151 static Instruction* createInstruction(
00152 string& name,
00153 RegisterReference* result,
00154 CalcYYLocType& location)
00155 {
00156 vector<RegisterReference*> operands;
00157 operands.push_back(result);
00158 return createInstruction(name, operands, location);
00159 }
00160
00161 static Instruction* createInstruction(
00162 string& name,
00163 CalcYYLocType& location)
00164 {
00165 vector<RegisterReference*> operands;
00166 return createInstruction(name, operands, location);
00167 }
00168
00169 static Instruction* createInstruction(
00170 string& name,
00171 TProgramCounter pc,
00172 CalcYYLocType& location)
00173 {
00174 return createInstruction(name, pc, NULL, location);
00175 }
00176
00177
00178 static Instruction* createInstruction(
00179 string& name,
00180 TProgramCounter pc,
00181 RegisterReference* operand,
00182 CalcYYLocType& location)
00183 {
00184 Instruction* inst = NULL;
00185
00186 try {
00187 inst = InstructionFactory::createInstruction(name, pc, operand);
00188 } catch (FennelExcn& ex) {
00189 throw CalcAssemblerException(ex.getMessage(), location);
00190 } catch (std::exception& ex) {
00191 throw CalcAssemblerException(ex.what(), location);
00192 }
00193
00194 if (inst == NULL) {
00195 stringstream errorStr("Error instantiating instruction: ");
00196 errorStr << name << " " << pc << ", ";
00197 if (operand) {
00198 errorStr << operand->toString();
00199 }
00200 throw CalcAssemblerException(errorStr.str(), location);
00201 }
00202 return inst;
00203 }
00204
00205 Instruction* createInstruction(
00206 string& name,
00207 string& function,
00208 vector<RegisterReference*>& operands,
00209 CalcYYLocType& location)
00210 {
00211 Instruction* inst = NULL;
00212
00213 try {
00214 inst = InstructionFactory::createInstruction(
00215 name, function, operands);
00216 } catch (FennelExcn& ex) {
00217 throw CalcAssemblerException(ex.getMessage(), location);
00218 } catch (std::exception& ex) {
00219 throw CalcAssemblerException(ex.what(), location);
00220 }
00221
00222 if (inst == NULL) {
00223 InstructionSignature sig(function, operands);
00224 stringstream errorStr("Error instantiating instruction: ");
00225 errorStr << name << " ";
00226 errorStr << sig.compute();
00227 errorStr << " not registered ";
00228 throw CalcAssemblerException(errorStr.str(), location);
00229 }
00230
00231 return inst;
00232 }
00233
00234 static void setTupleDatum(
00235 StandardTypeDescriptorOrdinal type,
00236 TupleDatum& tupleDatum,
00237 TupleAttributeDescriptor& desc,
00238 double value);
00239 static void setTupleDatum(
00240 StandardTypeDescriptorOrdinal type,
00241 TupleDatum& tupleDatum,
00242 TupleAttributeDescriptor& desc,
00243 uint64_t value);
00244 static void setTupleDatum(
00245 StandardTypeDescriptorOrdinal type,
00246 TupleDatum& tupleDatum,
00247 TupleAttributeDescriptor& desc,
00248 int64_t value);
00249 static void setTupleDatum(
00250 StandardTypeDescriptorOrdinal type,
00251 TupleDatum& tupleDatum,
00252 TupleAttributeDescriptor& desc,
00253 string value);
00254 static void setTupleDatum(
00255 StandardTypeDescriptorOrdinal type,
00256 TupleDatum& tupleDatum,
00257 TupleAttributeDescriptor& desc,
00258 PConstBuffer buffer);
00259
00260 protected:
00261 friend int CalcYYparse (void *);
00262
00263
00264
00266 void init();
00267
00276 void allocateTuples();
00277
00286 void bindRegisters();
00287
00302 template <typename T>
00303 void bindRegisterValue(
00304 RegisterReference::ERegisterSet setIndex,
00305 TRegisterIndex regIndex,
00306 T value)
00307 {
00308 try {
00309 StandardTypeDescriptorOrdinal regType = getRegisterType(
00310 setIndex, regIndex);
00311 TupleData* tupleData = getTupleData(setIndex);
00312 assert(tupleData != NULL);
00313 TupleDatum& tupleDatum = (*tupleData)[regIndex];
00314 TupleDescriptor& tupleDesc = getTupleDescriptor(setIndex);
00315 setTupleDatum(regType, tupleDatum, tupleDesc[regIndex], value);
00316 } catch (CalcAssemblerException& ex) {
00317
00318 throw ex;
00319 } catch (FennelExcn& ex) {
00320
00321 ostringstream errorStr("");
00322 errorStr << "Error binding register "
00323 << RegisterReference::toString(setIndex, regIndex)
00324 << ": " << ex.getMessage();
00325 throw CalcAssemblerException(
00326 errorStr.str(), getLexer().getLocation());
00327 } catch (exception& ex) {
00328
00329 ostringstream errorStr("");
00330 errorStr << "Error binding register: "
00331 << RegisterReference::toString(setIndex, regIndex)
00332 << ": " << ex.what();
00333 throw CalcAssemblerException(
00334 errorStr.str(), getLexer().getLocation());
00335 }
00336 }
00337
00353 template <typename T>
00354 void bindNextLiteral(T value)
00355 {
00356 bindRegisterValue<T>(RegisterReference::ELiteral, mLiteralIndex, value);
00357 mLiteralIndex++;
00358 }
00359
00365 void bindLiteralDone();
00366
00367
00368
00373 void selectRegisterSet(RegisterReference::ERegisterSet setIndex);
00374
00381 void addRegister(
00382 StandardTypeDescriptorOrdinal regType,
00383 uint cbStorage = 0);
00384
00391 void addRegister(
00392 RegisterReference::ERegisterSet setIndex,
00393 StandardTypeDescriptorOrdinal regType,
00394 uint cbStorage = 0);
00395
00396
00397
00398
00403 void addInstruction(Instruction* inst);
00404
00405
00406
00412 TRegisterIndex getRegisterSize(RegisterReference::ERegisterSet setIndex);
00413
00422 RegisterReference* getRegister(
00423 RegisterReference::ERegisterSet setIndex,
00424 TRegisterIndex regIndex);
00425
00434 StandardTypeDescriptorOrdinal getRegisterType(
00435 RegisterReference::ERegisterSet setIndex,
00436 TRegisterIndex regIndex);
00437
00443 TupleData* getTupleData(RegisterReference::ERegisterSet setIndex);
00444
00450 TupleDescriptor& getTupleDescriptor(
00451 RegisterReference::ERegisterSet setIndex);
00452
00459 void checkPC(TProgramCounter pc, CalcYYLocType& loc) {
00460 assert(mCalc->mCode.size() > 0);
00461 if (pc >= static_cast<TProgramCounter>(mCalc->mCode.size())) {
00462 ostringstream errorStr("");
00463 errorStr << "Invalid PC " << pc << ": PC should be between 0 and "
00464 << (mCalc->mCode.size() - 1);
00465 throw CalcAssemblerException(errorStr.str(), loc);
00466 }
00467 }
00468
00476 void saveMaxPC(TProgramCounter pc)
00477 {
00478 assert(pc > 0);
00479 if (pc > mMaxPC) {
00480 mMaxPC = pc;
00481 mMaxPCLoc = getLexer().getLocation();
00482 }
00483 }
00484
00485 protected:
00486 CalcLexer mLexer;
00487 Calculator* mCalc;
00488
00490 TupleDescriptor mRegisterSetDescriptor[RegisterReference::ELastSet];
00491
00495 TupleData* mRegisterTupleData[RegisterReference::ELastSet];
00498 FixedBuffer* mBuffers[RegisterReference::ELastSet];
00499
00501 StandardTypeDescriptorFactory mTypeFactory;
00502
00504 RegisterReference::ERegisterSet mCurrentRegSet;
00505
00507 TRegisterIndex mLiteralIndex;
00508
00510 TProgramCounter mMaxPC;
00511 CalcYYLocType mMaxPCLoc;
00512 };
00513
00514 FENNEL_END_NAMESPACE
00515
00516 #endif
00517
00518