1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

Add pragmas to funC for precise control of computation order (#589)

* FunC pragmas: allow-post-modification and compute-asm-ltr

* Warn if #pragma is enabled only in included files

* Add tests for new pragmas

* Add special ops for "allow-post-modification" only when needed

* Update FunC version to 0.4.1

* Allow empty inlines (#10)

Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
EmelyanenkoK 2023-01-13 12:45:04 +03:00 committed by GitHub
parent 6b49d6a382
commit 653c88aa9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 344 additions and 61 deletions

View file

@ -39,7 +39,7 @@ extern std::string generated_from;
constexpr int optimize_depth = 20;
const std::string func_version{"0.4.0"};
const std::string func_version{"0.4.1"};
enum Keyword {
_Eof = -1,
@ -306,7 +306,7 @@ struct TmpVar {
sym_idx_t name;
int coord;
std::unique_ptr<SrcLocation> where;
size_t modify_forbidden = 0;
std::vector<std::function<void(const SrcLocation &)>> on_modification;
TmpVar(var_idx_t _idx, int _cls, TypeExpr* _type = 0, SymDef* sym = 0, const SrcLocation* loc = 0);
void show(std::ostream& os, int omit_idx = 0) const;
void dump(std::ostream& os) const;
@ -681,6 +681,7 @@ typedef std::vector<FormalArg> FormalArgList;
struct AsmOpList;
struct CodeBlob {
enum { _AllowPostModification = 1, _ComputeAsmLtr = 2 };
int var_cnt, in_var_cnt, op_cnt;
TypeExpr* ret_type;
std::string name;
@ -689,6 +690,7 @@ struct CodeBlob {
std::unique_ptr<Op> ops;
std::unique_ptr<Op>* cur_ops;
std::stack<std::unique_ptr<Op>*> cur_ops_stack;
int flags = 0;
CodeBlob(TypeExpr* ret = nullptr) : var_cnt(0), in_var_cnt(0), op_cnt(0), ret_type(ret), cur_ops(&ops) {
}
template <typename... Args>
@ -729,19 +731,9 @@ struct CodeBlob {
void generate_code(AsmOpList& out_list, int mode = 0);
void generate_code(std::ostream& os, int mode = 0, int indent = 0);
void mark_modify_forbidden(var_idx_t idx) {
++vars.at(idx).modify_forbidden;
}
void unmark_modify_forbidden(var_idx_t idx) {
assert(vars.at(idx).modify_forbidden > 0);
--vars.at(idx).modify_forbidden;
}
void check_modify_forbidden(var_idx_t idx, const SrcLocation& here) const {
if (vars.at(idx).modify_forbidden) {
throw src::ParseError{here, PSTRING() << "Modifying local variable " << vars[idx].to_string()
<< " after using it in the same expression"};
void on_var_modification(var_idx_t idx, const SrcLocation& here) const {
for (auto& f : vars.at(idx).on_modification) {
f(here);
}
}
};
@ -855,7 +847,7 @@ extern std::vector<SymDef*> glob_func, glob_vars;
// defined in parse-func.cpp
bool parse_source(std::istream* is, const src::FileDescr* fdescr);
bool parse_source_file(const char* filename, src::Lexem lex = {});
bool parse_source_file(const char* filename, src::Lexem lex = {}, bool is_main = false);
bool parse_source_stdin();
extern std::stack<src::SrcLocation> inclusion_locations;
@ -1700,6 +1692,41 @@ extern int verbosity, indent, opt_level;
extern bool stack_layout_comments, op_rewrite_comments, program_envelope, asm_preamble, interactive;
extern std::string generated_from, boc_output_filename;
class GlobalPragma {
public:
explicit GlobalPragma(std::string name) : name_(std::move(name)) {
}
const std::string& name() const {
return name_;
}
bool enabled() const {
return enabled_;
}
void enable(SrcLocation loc) {
enabled_ = true;
locs_.push_back(std::move(loc));
}
void check_enable_in_libs() {
if (locs_.empty()) {
return;
}
for (const SrcLocation& loc : locs_) {
if (loc.fdescr->is_main) {
return;
}
}
locs_[0].show_warning(PSTRING() << "#pragma " << name_
<< " is enabled in included libraries, it may change the behavior of your code. "
<< "Add this #pragma to the main source file to suppress this warning.");
}
private:
std::string name_;
bool enabled_ = false;
std::vector<SrcLocation> locs_;
};
extern GlobalPragma pragma_allow_post_modification, pragma_compute_asm_ltr;
/*
*
* OUTPUT CODE GENERATOR