void UnitEmitter::addTrivialPseudoMain() { initMain(0, 0); auto const mfe = getMain(); emitOp(OpInt); emitInt64(1); emitOp(OpRetC); mfe->maxStackCells = 1; mfe->finish(bcPos(), false); recordFunction(mfe); TypedValue mainReturn; mainReturn.m_data.num = 1; mainReturn.m_type = KindOfInt64; m_mainReturn = mainReturn; m_mergeOnly = true; }
static void emit(int c, const char *p1) { char ap [PATH_MAX]; SE; emitOp(c, realpath(p1, ap), 0); RE; }
std::unique_ptr<UnitEmitter> createFatalUnit(StringData* filename, const MD5& md5, FatalOp /*op*/, StringData* err) { auto ue = std::make_unique<UnitEmitter>(md5); ue->m_filepath = filename; ue->initMain(1, 1); ue->emitOp(OpString); ue->emitInt32(ue->mergeLitstr(err)); ue->emitOp(OpFatal); ue->emitByte(static_cast<uint8_t>(FatalOp::Runtime)); FuncEmitter* fe = ue->getMain(); fe->maxStackCells = 1; // XXX line numbers are bogus fe->finish(ue->bcPos(), false); ue->recordFunction(fe); return ue; }
int unlink(const char *p) { int r; char b [PATH_MAX]; char *rp; static int (*ounlink) (const char *)= 0; DP; R(unlink); rp = realpath(p, b); r = ounlink(p); if (!r) emitOp('d', rp, 0); DD; return r; }
int renameat(int fd1, const char *p1, int fd2, const char *p2) { int r; D; if (fd1 != AT_FDCWD || fd2 != AT_FDCWD) { static int (*orenameat) (const char *, const char *)= 0; R(renameat); r = orenameat(p1, p2); if (!r) emitOp('R', p2, p1); } else r = rename(p1, p2); DD; return r; }
int openat64(int fd, const char *p, int f, mode_t m) { int r; DP; if (fd != AT_FDCWD) { static int (*oopenat64) (int, const char *, int, mode_t)= 0; R(openat64); r = oopenat64(fd, p, f, m); if (r >= 0) emitOp(f & wmode ? 'W' : 'R', p, 0); } else r = open64(p, f, m); DD; return r; }
int rename(const char *p1, const char *p2) { int r; char b1 [PATH_MAX]; char *rp1 = realpath(p1, b1); static int (*orename) (const char *, const char *)= 0; D; R(rename); r = orename(p1, p2); if (!r) { char b2 [PATH_MAX]; char *rp2 = realpath(p2, b2); emitOp(rp1 ? 'm' : 'M', rp2, rp1); } DD; return r; }
int unlinkat(int fd, const char *p, int f) { int r; DP; if (fd != AT_FDCWD) { static int (*ounlinkat) (int fd, const char *p, int f); R(unlinkat); r = ounlinkat(fd, p, f); if (!r) emitOp('D', p, 0); assert(0); } else if (f & AT_REMOVEDIR) r = rmdir(p); else r = unlink(p); DD; return r; }
static void fdemit(int c, int fd) { char ap [PATH_MAX]; int ok; SE; #ifdef F_GETPATH ok = -1 != fcntl(fd, F_GETPATH, ap); #else { ssize_t written; char fdpath [100]; snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd); written = readlink(fdpath, ap, sizeof(ap)); ok = written >= 0 && written < sizeof(ap); if (ok) ap[written] = 0; } #endif emitOp(c, ok ? ap : 0, 0); RE; }
void Parser::emitOp(Ast &ast) { Ast copy = ast; emitOp(std::move(copy)); }
void Parser::emitOp(Op op, double d) { Ast &&ast = Ast::create(op); ast.d = d; emitOp(ast); }
void Parser::emitOp(Op op, int i) { Ast &&ast = Ast::create(op); ast.i = i; emitOp(ast); }
int Parser::parse() { std::stack<Token> stack; ast.op = OP_HLT; ast.i = 0; lastTokenId = TOK_NONE; lastOp = -1; tok = scanner.getNextToken(); while (tok.id != TOK_EOF) { bool expectUnary = lastTokenId == TOK_LPAREN || lastTokenId == TOK_NONE || canBePrefix(lastTokenId) || canBeInfix(lastTokenId); bool expectExpr = lastTokenId == TOK_NONE || lastTokenId == TOK_LPAREN || canBePrefix(lastTokenId) || canBeInfix(lastTokenId); switch (tok.id) { default: raiseError("unknown token"); return 1; case TOK_ERROR: raiseError(tok.err); return 1; case TOK_PLUS: if (expectUnary) tok.id = TOK_UN_PLUS; else tok.id = TOK_OP_ADD; continue; case TOK_MINUS: if (expectUnary) tok.id = TOK_UN_NEG; else tok.id = TOK_OP_SUB; continue; case TOK_ARG: if (canBeValue(lastTokenId)) { raiseError("unexpected primary value"); return 1; } if (tok.i > UCHAR_MAX) { raiseError("argument number out of range"); return 1; } emitOp(OP_ARG, (unsigned char)(tok.i)); break; case TOK_LIT: if (canBeValue(lastTokenId)) { raiseError("unexpected primary value"); return 1; } emitOp(OP_CONST, tok.d); break; case TOK_F_PI: if (canBeValue(lastTokenId)) { raiseError("unexpected primary value"); return 1; } emitOp(OP_PI); break; case TOK_F_E: if (canBeValue(lastTokenId)) { raiseError("unexpected primary value"); return 1; } emitOp(OP_E); break; case TOK_UN_PLUS: // unary plus is a noop break; case TOK_LPAREN: if (!canBeFunction(lastTokenId) && !expectExpr) { raiseError("unexpected open parenthesis"); return 1; } stack.push(tok); break; case TOK_F_SQRT: case TOK_F_SIN: case TOK_F_COS: case TOK_F_TAN: case TOK_F_ASIN: case TOK_F_ACOS: case TOK_F_ATAN: case TOK_F_SINH: case TOK_F_COSH: case TOK_F_TANH: case TOK_F_ASINH: case TOK_F_ACOSH: case TOK_F_ATANH: case TOK_F_EXP: case TOK_F_LOG: case TOK_F_ERF: case TOK_F_ERFC: case TOK_F_ABS: case TOK_F_FLOOR: case TOK_F_CEIL: case TOK_F_ROUND: case TOK_F_TRUNC: case TOK_F_POW: case TOK_UN_NEG: if (canBeValue(lastTokenId)) { raiseError("unexpected prefix operator"); return 1; } stack.push(tok); break; case TOK_COMMA: while (stack.size() > 0 && stack.top().id != TOK_LPAREN) { emitOp(getOperator(stack.top().id)); stack.pop(); } if (stack.size() <= 0 || stack.top().id != TOK_LPAREN) { raiseError("misplaced comma"); return 1; } break; case TOK_RPAREN: while (stack.size() > 0 && stack.top().id != TOK_LPAREN) { emitOp(getOperator(stack.top().id)); stack.pop(); } if (stack.size() <= 0 || stack.top().id != TOK_LPAREN) { raiseError("mismatched parenthesis"); return 1; } stack.pop(); while (stack.size() > 0 && canBePrefix(stack.top().id)) { emitOp(getOperator(stack.top().id)); stack.pop(); } break; case TOK_OP_ADD: case TOK_OP_SUB: case TOK_OP_MUL: case TOK_OP_DIV: case TOK_OP_POW: if (!canBeValue(lastTokenId)) { raiseError("unexpected operator"); return 1; } while (stack.size() > 0 && canBeOperation(stack.top().id)) { if (isRightAssociative(tok.id)) { if (getPrecedence(tok.id) < getPrecedence(stack.top().id)) { emitOp(getOperator(stack.top().id)); stack.pop(); } else break; } else { if (getPrecedence(tok.id) <= getPrecedence(stack.top().id)) { emitOp(getOperator(stack.top().id)); stack.pop(); } else break; } } stack.push(tok); break; } lastTokenId = tok.id; tok = scanner.getNextToken(); } if (!canBeValue(lastTokenId)) { raiseError("unexpected program end"); return 1; } while (stack.size() > 0) { if (stack.top().id == TOK_LPAREN || stack.top().id == TOK_RPAREN) { raiseError("mismatched parenthesis"); return 1; } else { emitOp(getOperator(stack.top().id)); stack.pop(); } } return 0; }
Bytecode::Bytecode() : size(0) { emitOp(FRAME); emitOp(INVK); emitReference(getLabel("main")); emitOp(EXIT); }