diff --git a/CMakeLists.txt b/CMakeLists.txt index 98a0b5d52..1ffaca590 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ set(COMPILER components/compiler/errorhandler.cpp components/compiler/parser.cpp components/compiler/scanner.cpp components/compiler/streamerrorhandler.cpp components/compiler/locals.cpp components/compiler/literals.cpp - components/compiler/output.cpp) + components/compiler/output.cpp components/compiler/generator.cpp) file(GLOB COMPILER_HEADER components/compiler/*.hpp) source_group(compiler FILES ${COMPILER} ${COMPILER_HEADER}) diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp new file mode 100644 index 000000000..e73909d90 --- /dev/null +++ b/components/compiler/generator.cpp @@ -0,0 +1,120 @@ + +#include "generator.hpp" + +#include + +#include "literals.hpp" + +namespace +{ + Interpreter::Type_Code segment0 (unsigned int c, unsigned int arg0) + { + assert (c<64); + return (c<<24) | (arg0 & 0xffffff); + } + + Interpreter::Type_Code segment1 (unsigned int c, unsigned int arg0, unsigned int arg1) + { + assert (c<64); + return 0x40000000 | (c<<24) | ((arg0 & 0xfff)<<12) | (arg1 & 0xfff); + } + + Interpreter::Type_Code segment2 (unsigned int c, unsigned int arg0) + { + assert (c<1024); + return 0x80000000 | (c<<20) | (arg0 & 0xfffff); + } + + Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0) + { + assert (c<1024); + return 0xc0000000 | (c<<20) | (arg0 & 0xffff); + } + + Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0, unsigned int arg1) + { + assert (c<1024); + return 0xc4000000 | (c<<16) | ((arg0 & 0xff)<<8) | (arg1 & 0xff); + } + + Interpreter::Type_Code segment5 (unsigned int c) + { + assert (c<67108864); + return 0xc8000000 | c; + } + + void opPushInt (Compiler::Generator::CodeContainer& code, int value) + { + code.push_back (segment0 (0, value)); + } + + void opFetchIntLiteral (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (4)); + } + + void opFetchFloatLiteral (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (5)); + } + + void opIntToFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (3)); + } + + void opStoreLocalShort (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (0)); + } + + void opStoreLocalLong (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (1)); + } + + void opStoreLocalFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (2)); + } +} + +namespace Compiler +{ + namespace Generator + { + void assignIntToLocal (CodeContainer& code, Literals& literals, char localType, + int localIndex, int value) + { + int index = literals.addInteger (value); + + opPushInt (code, localIndex); + opPushInt (code, index); + opFetchIntLiteral (code); + + switch (localType) + { + case 'f': + + opIntToFloat (code); + opStoreLocalFloat (code); + break; + + case 's': + + opStoreLocalShort (code); + break; + + case 'l': + + opStoreLocalLong (code); + break; + + default: + + assert (0); + } + } + } +} + diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp new file mode 100644 index 000000000..cab5f3bda --- /dev/null +++ b/components/compiler/generator.hpp @@ -0,0 +1,22 @@ +#ifndef COMPILER_GENERATOR_H_INCLUDED +#define COMPILER_GENERATOR_H_INCLUDED + +#include + +#include + +namespace Compiler +{ + class Literals; + + namespace Generator + { + typedef std::vector CodeContainer; + + void assignIntToLocal (CodeContainer& code, Literals& literals, char localType, + int localIndex, int value); + } +} + +#endif + diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index d88680edc..35c79ff60 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -6,6 +6,7 @@ #include "errorhandler.hpp" #include "skipparser.hpp" #include "locals.hpp" +#include "generator.hpp" namespace Compiler { @@ -17,6 +18,17 @@ namespace Compiler bool LineParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) { + if (mState==SetLocalToState) + { + Generator::assignIntToLocal (mCode, mLiterals, mLocals.getType (mName), + mLocals.getIndex (mName), value); + + mState = EndState; + mName.clear(); + + return true; + } + return Parser::parseInt (value, loc, scanner); } @@ -55,6 +67,23 @@ namespace Compiler return true; } + if (mState==SetState) + { + // local variable? + char type = mLocals.getType (name); + if (type!=' ') + { + mName = name; + mState = SetLocalVarState; + return true; + } + + getErrorHandler().error ("unknown variable", loc); + SkipParser skip (getErrorHandler(), getContext()); + scanner.scan (skip); + return false; + } + return Parser::parseName (name, loc, scanner); } @@ -67,8 +96,14 @@ namespace Compiler case Scanner::K_short: mState = ShortState; return true; case Scanner::K_long: mState = LongState; return true; case Scanner::K_float: mState = FloatState; return true; + case Scanner::K_set: mState = SetState; return true; } } + else if (mState==SetLocalVarState && keyword==Scanner::K_to) + { + mState = SetLocalToState; + return true; + } return Parser::parseKeyword (keyword, loc, scanner); } @@ -84,6 +119,7 @@ namespace Compiler void LineParser::reset() { mState = BeginState; + mName.clear(); } } diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index 43d79883d..b69ac803e 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -20,6 +20,7 @@ namespace Compiler { BeginState, ShortState, LongState, FloatState, + SetState, SetLocalVarState, SetLocalToState, EndState }; @@ -27,6 +28,7 @@ namespace Compiler Literals& mLiterals; std::vector& mCode; State mState; + std::string mName; public: diff --git a/components/compiler/locals.cpp b/components/compiler/locals.cpp index eefe27a03..d93e73849 100644 --- a/components/compiler/locals.cpp +++ b/components/compiler/locals.cpp @@ -21,11 +21,22 @@ namespace Compiler throw std::logic_error ("unknown variable type"); } - bool Locals::search (char type, const std::string& name) const + int Locals::searchIndex (char type, const std::string& name) const { const std::vector& collection = get (type); - return std::find (collection.begin(), collection.end(), name)!=collection.end(); + std::vector::const_iterator iter = + std::find (collection.begin(), collection.end(), name); + + if (iter==collection.end()) + return -1; + + return iter-collection.begin(); + } + + bool Locals::search (char type, const std::string& name) const + { + return searchIndex (type, name)!=-1; } std::vector& Locals::get (char type) @@ -54,6 +65,21 @@ namespace Compiler return ' '; } + int Locals::getIndex (const std::string& name) const + { + int index = searchIndex ('s', name); + + if (index!=-1) + return index; + + index = searchIndex ('l', name); + + if (index!=-1) + return index; + + return searchIndex ('f', name); + } + void Locals::write (std::ostream& localFile) const { localFile diff --git a/components/compiler/locals.hpp b/components/compiler/locals.hpp index c12ba371a..fdd0a6b29 100644 --- a/components/compiler/locals.hpp +++ b/components/compiler/locals.hpp @@ -17,6 +17,8 @@ namespace Compiler const std::vector& get (char type) const; + int searchIndex (char type, const std::string& name) const; + bool search (char type, const std::string& name) const; std::vector& get (char type); @@ -26,6 +28,9 @@ namespace Compiler char getType (const std::string& name) const; ///< 's': short, 'l': long, 'f': float, ' ': does not exist. + int getIndex (const std::string& name) const; + ///< return index for local variable \a name (-1: does not exist). + void write (std::ostream& localFile) const; ///< write declarations to file. diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt new file mode 100644 index 000000000..1449a6194 --- /dev/null +++ b/components/interpreter/docs/vmformat.txt @@ -0,0 +1,62 @@ +Note: a word is considered to be 32 bit long. + +Header (4 words): +word: number of words in code block +word: number of words in integer literal block +word: number of words in float literal block +word: number of words in string literal block + +Body (variable length): +code block +integer literal block (contains a collection of 1 word long integers) +float literal block (contains a collection of 1 word long floating point numbers) +string literal block (contains a collection of strings of variable length, word-padded) + +Code bit-patterns: + +3322222222221111111111 +10987654321098765432109876543210 +00ccccccAAAAAAAAAAAAAAAAAAAAAAAA segment 0: 64 opcodes, 1 24-bit argument +01ccccccAAAAAAAAAAAABBBBBBBBBBBB segment 1: 64 opcodes, 2 12-bit arguments +10ccccccccccAAAAAAAAAAAAAAAAAAAA segment 2: 1024 opcodes, 1 20-bit argument +110000ccccccccccAAAAAAAAAAAAAAAA segment 3: 1024 opcodes, 1 16-bit argument +110001ccccccccccAAAAAAAABBBBBBBB segment 4: 1024 opcodes, 2 8-bit arguments +110010cccccccccccccccccccccccccc segment 5: 67108864 opcodes, no arguments +other bit-patterns reserved + +legent: +c: code +A: argument 0 +B: argument 1 + +Segment 0: +op 0: push A +opcodes 1-31 unused +opcodes 32-63 reserved for extensions + +Segment 1: +opcodes 0-31 unused +opcodes 32-63 reserved for extensions + +Segment 2: +opcodes 0-511 unused +opcodes 512-1023 reserved for extensions + +Segment 3: +opcodes 0-511 unused +opcodes 512-1023 reserved for extensions + +Segment 4: +opcodes 0-511 unused +opcodes 512-1023 reserved for extensions + +Segment 5: +op 0: store stack[0] in local short stack[1] and pop twice +op 1: store stack[0] in local long stack[1] and pop twice +op 2: store stack[0] in local float stack[1] and pop twice +op 3: convert stack[0] from integer to float +op 4: replace stack[0] with integer literal index stack[0] +op 5: replace stack[0] with float literal index stack[0] +opcodes 6-33554431 unused +opcodes 33554432-67108863 reserved for extensions + diff --git a/components/interpreter/types.hpp b/components/interpreter/types.hpp index 4189914d6..28ad51dd1 100644 --- a/components/interpreter/types.hpp +++ b/components/interpreter/types.hpp @@ -7,9 +7,9 @@ namespace Interpreter typedef unsigned int Type_Data; // 32 bit - typedef unsigned int Type_Integer; // 32 bit + typedef int Type_Integer; // 32 bit - typedef unsigned int Type_Float; // 32 bit + typedef float Type_Float; // 32 bit } #endif