@@ -65,9 +65,50 @@ class Assembly
6565 }
6666
6767 std::optional<uint8_t > eofVersion () const { return m_eofVersion; }
68+ bool supportsFunctions () const { return m_eofVersion.has_value (); }
6869 bool supportsRelativeJumps () const { return m_eofVersion.has_value (); }
6970 AssemblyItem newTag () { assertThrow (m_usedTags < 0xffffffff , AssemblyException, " " ); return AssemblyItem (Tag, m_usedTags++); }
7071 AssemblyItem newPushTag () { assertThrow (m_usedTags < 0xffffffff , AssemblyException, " " ); return AssemblyItem (PushTag, m_usedTags++); }
72+ AssemblyItem newFunctionCall (uint16_t _functionID)
73+ {
74+ solAssert (_functionID < m_codeSections.size (), " Call to undeclared function." );
75+ solAssert (_functionID > 0 , " Cannot call call section 0" );
76+ auto const & section = m_codeSections.at (_functionID);
77+ if (section.outputs != 0x80 )
78+ return AssemblyItem::functionCall (_functionID, section.inputs , section.outputs );
79+ else
80+ return AssemblyItem::jumpF (_functionID, section.inputs );
81+ }
82+
83+ AssemblyItem newFunctionReturn ()
84+ {
85+ return AssemblyItem::functionReturn (m_codeSections.at (m_currentCodeSection).outputs );
86+ }
87+
88+ uint16_t createFunction (uint8_t _args, uint8_t _rets)
89+ {
90+ size_t functionID = m_codeSections.size ();
91+ solAssert (functionID < 1024 , " Too many functions." );
92+ solAssert (m_currentCodeSection == 0 , " Functions need to be declared from the main block." );
93+ solAssert (_rets <= 0x80 , " Too many function returns." );
94+ m_codeSections.emplace_back (CodeSection{_args, _rets, {}});
95+ return static_cast <uint16_t >(functionID);
96+ }
97+
98+ void beginFunction (uint16_t _functionID)
99+ {
100+ solAssert (m_currentCodeSection == 0 , " Atempted to begin a function before ending the last one." );
101+ solAssert (_functionID < m_codeSections.size (), " Attempt to begin an undeclared function." );
102+ auto & section = m_codeSections.at (_functionID);
103+ solAssert (section.items .empty (), " Function already defined." );
104+ m_currentCodeSection = _functionID;
105+ }
106+ void endFunction ()
107+ {
108+ solAssert (m_currentCodeSection != 0 , " End function without begin function." );
109+ m_currentCodeSection = 0 ;
110+ }
111+
71112 // / Returns a tag identified by the given name. Creates it if it does not yet exist.
72113 AssemblyItem namedTag (std::string const & _name, size_t _params, size_t _returns, std::optional<uint64_t > _sourceID);
73114 AssemblyItem newData (bytes const & _data) { util::h256 h (util::keccak256 (util::asString (_data))); m_data[h] = _data; return AssemblyItem (PushData, h); }
@@ -111,6 +152,16 @@ class Assembly
111152 return append (AssemblyItem::returnContract (_containerId));
112153 }
113154
155+ AssemblyItem appendFunctionCall (uint16_t _functionID)
156+ {
157+ return append (newFunctionCall (_functionID));
158+ }
159+
160+ AssemblyItem appendFunctionReturn ()
161+ {
162+ return append (newFunctionReturn ());
163+ }
164+
114165 AssemblyItem appendJump () { auto ret = append (newPushTag ()); append (Instruction::JUMP); return ret; }
115166 AssemblyItem appendJumpI () { auto ret = append (newPushTag ()); append (Instruction::JUMPI); return ret; }
116167 AssemblyItem appendJump (AssemblyItem const & _tag) { auto ret = append (_tag.pushTag ()); append (Instruction::JUMP); return ret; }
0 commit comments