// Tries to evaluate the integer constant of a value. The \p depth is used // to limit the complexity. ConstantTracker::IntConst ConstantTracker::getIntConst(SILValue val, int depth) { // Don't spend too much time with constant evaluation. if (depth >= 10) return IntConst(); SILInstruction *I = getDef(val); if (!I) return IntConst(); if (auto *IL = dyn_cast<IntegerLiteralInst>(I)) { return IntConst(IL->getValue(), IL->getFunction() != F); } if (auto *BI = dyn_cast<BuiltinInst>(I)) { if (constCache.count(BI) != 0) return constCache[BI]; IntConst builtinConst = getBuiltinConst(BI, depth + 1); constCache[BI] = builtinConst; return builtinConst; } return IntConst(); }
ConstantTracker::IntConst ConstantTracker::getBuiltinConst(BuiltinInst *BI, int depth) { const BuiltinInfo &Builtin = BI->getBuiltinInfo(); OperandValueArrayRef Args = BI->getArguments(); switch (Builtin.ID) { default: break; // Fold comparison predicates. #define BUILTIN(id, name, Attrs) #define BUILTIN_BINARY_PREDICATE(id, name, attrs, overload) \ case BuiltinValueKind::id: #include "swift/AST/Builtins.def" { IntConst lhs = getIntConst(Args[0], depth); IntConst rhs = getIntConst(Args[1], depth); if (lhs.isValid && rhs.isValid) { return IntConst(constantFoldComparison(lhs.value, rhs.value, Builtin.ID), lhs.isFromCaller || rhs.isFromCaller); } break; } case BuiltinValueKind::SAddOver: case BuiltinValueKind::UAddOver: case BuiltinValueKind::SSubOver: case BuiltinValueKind::USubOver: case BuiltinValueKind::SMulOver: case BuiltinValueKind::UMulOver: { IntConst lhs = getIntConst(Args[0], depth); IntConst rhs = getIntConst(Args[1], depth); if (lhs.isValid && rhs.isValid) { bool IgnoredOverflow; return IntConst(constantFoldBinaryWithOverflow(lhs.value, rhs.value, IgnoredOverflow, getLLVMIntrinsicIDForBuiltinWithOverflow(Builtin.ID)), lhs.isFromCaller || rhs.isFromCaller); } break; } case BuiltinValueKind::SDiv: case BuiltinValueKind::SRem: case BuiltinValueKind::UDiv: case BuiltinValueKind::URem: { IntConst lhs = getIntConst(Args[0], depth); IntConst rhs = getIntConst(Args[1], depth); if (lhs.isValid && rhs.isValid && rhs.value != 0) { bool IgnoredOverflow; return IntConst(constantFoldDiv(lhs.value, rhs.value, IgnoredOverflow, Builtin.ID), lhs.isFromCaller || rhs.isFromCaller); } break; } case BuiltinValueKind::And: case BuiltinValueKind::AShr: case BuiltinValueKind::LShr: case BuiltinValueKind::Or: case BuiltinValueKind::Shl: case BuiltinValueKind::Xor: { IntConst lhs = getIntConst(Args[0], depth); IntConst rhs = getIntConst(Args[1], depth); if (lhs.isValid && rhs.isValid) { return IntConst(constantFoldBitOperation(lhs.value, rhs.value, Builtin.ID), lhs.isFromCaller || rhs.isFromCaller); } break; } case BuiltinValueKind::Trunc: case BuiltinValueKind::ZExt: case BuiltinValueKind::SExt: case BuiltinValueKind::TruncOrBitCast: case BuiltinValueKind::ZExtOrBitCast: case BuiltinValueKind::SExtOrBitCast: { IntConst val = getIntConst(Args[0], depth); if (val.isValid) { return IntConst(constantFoldCast(val.value, Builtin), val.isFromCaller); } break; } } return IntConst(); }
Token DnInLexer::nextToken() { while(c != LEX_EOF) { switch(c) { case ' ': case '\t': case '\n': case '\r': skipSpaces(); continue; case '=': consume(); if (c == '=') { // == consume(); return Token(EQUALEQUAL, "=="); } else { return Token(EQUAL, "="); } case '+': consume(); return Token(PLUS, "+"); case '-': consume(); return Token(MINUS, "-"); case '/': consume(); return Token(DIV, "/"); case '*': consume(); return Token(MUL, "*"); case '%': consume(); return Token(MOD, "%"); case '&': consume(); return Token(AND, "&"); case '!': consume(); return Token(NOT, "!"); case '<': consume(); if (c == '=') { // <= consume(); return Token(LESSEQUAL, "<="); } else { return Token(LESS, "<"); } case '>': consume(); if (c == '=') { // >= consume(); return Token(ABOVEEQUAL, ">="); } else { return Token(ABOVE, ">"); } case '\"': /* "hoge" (string) */ if(isString()) return String(); default: if(isDecimal()) { /* {D} */ if(isFloat()) return FloatConst(); else return IntConst(); }else { /* {L} It could be id or reserved word */ return Addr(); } break; } } return Token(EOF_TYPE, "<EOF>"); }