static void makeAsmTag ( const vString *const name, const vString *const operator, const boolean labelCandidate, const boolean nameFollows) { if (vStringLength (name) > 0) { boolean found; const AsmKind kind = operatorKind (operator, &found); if (found) { if (kind != K_NONE) makeSimpleTag (name, AsmKinds, kind); } else if (isDefineOperator (operator)) { if (! nameFollows) makeSimpleTag (name, AsmKinds, K_DEFINE); } else if (labelCandidate) { operatorKind (name, &found); if (! found) makeSimpleTag (name, AsmKinds, K_LABEL); } } }
void UnaryOperator::doPrint(PrintContext &context) const { switch (operatorKind()) { case DEREFERENCE: context.out() << '*'; break; case REFERENCE: context.out() << '&'; break; case BITWISE_NOT: context.out() << '~'; break; case LOGICAL_NOT: context.out() << '!'; break; case NEGATION: context.out() << '-'; break; case PREFIX_INCREMENT: context.out() << "++"; break; case PREFIX_DECREMENT: context.out() << "--"; break; default: unreachable(); break; } int precedence = this->precedence(); int operandPrecedence = operand()->precedence(); int absPrecedence = abs(precedence); int absOperandPrecedence = abs(operandPrecedence); bool operandInBraces = absOperandPrecedence > absPrecedence; /* Avoid too many minuses in a row. */ if (operatorKind() == NEGATION || operatorKind() == PREFIX_DECREMENT) { if (auto unary = operand()->as<UnaryOperator>()) { if (unary->operatorKind() == NEGATION || unary->operatorKind() == PREFIX_DECREMENT) { operandInBraces = true; } } } if (operandInBraces) { context.out() << '('; } operand()->print(context); if (operandInBraces) { context.out() << ')'; } }
Expression *UnaryOperator::rewrite() { rewriteChild(operand_); switch (operatorKind()) { case DEREFERENCE: { if (UnaryOperator *unary = operand()->as<UnaryOperator>()) { if (unary->operatorKind() == REFERENCE) { return unary->releaseOperand().release(); } } return this; } case LOGICAL_NOT: { while (Typecast *typecast = operand()->as<Typecast>()) { if (typecast->type()->isScalar() && typecast->operand()->getType()->isScalar()) { setOperand(typecast->releaseOperand()); } else { break; } } if (BinaryOperator *binary = operand()->as<BinaryOperator>()) { switch (binary->operatorKind()) { case BinaryOperator::EQ: binary->setOperatorKind(BinaryOperator::NEQ); return releaseOperand().release(); case BinaryOperator::NEQ: binary->setOperatorKind(BinaryOperator::EQ); return releaseOperand().release(); case BinaryOperator::LT: binary->setOperatorKind(BinaryOperator::GEQ); return releaseOperand().release(); case BinaryOperator::LEQ: binary->setOperatorKind(BinaryOperator::GT); return releaseOperand().release(); case BinaryOperator::GT: binary->setOperatorKind(BinaryOperator::LEQ); return releaseOperand().release(); case BinaryOperator::GEQ: binary->setOperatorKind(BinaryOperator::LT); return releaseOperand().release(); default: break; } } if (UnaryOperator *unary = operand()->as<UnaryOperator>()) { if (unary->operatorKind() == LOGICAL_NOT) { if (unary->operand()->getType()->size() == 1) { return unary->releaseOperand().release(); } } } return this; } default: return this; } }
int UnaryOperator::precedence() const { switch (operatorKind()) { case DEREFERENCE: case REFERENCE: case BITWISE_NOT: case LOGICAL_NOT: case NEGATION: case PREFIX_INCREMENT: case PREFIX_DECREMENT: return -3; default: unreachable(); return 0; } }
const Type *UnaryOperator::getType() const { const Type *operandType = operand()->getType(); switch (operatorKind()) { case REFERENCE: { return tree().makePointerType(operandType); } case DEREFERENCE: if (const PointerType *pointerType = operandType->as<PointerType>()) { return pointerType->pointeeType(); } else { return tree().makeErroneousType(); } break; case BITWISE_NOT: if (operandType->isInteger()) { return tree().integerPromotion(operandType); } else { return tree().makeErroneousType(); } case LOGICAL_NOT: if (operandType->isScalar()) { return tree().makeIntegerType(tree().intSize(), false); } else { return tree().makeErroneousType(); } break; case NEGATION: { if (operandType->isInteger() || operandType->isFloat()) { return operandType; } else { return tree().makeErroneousType(); } break; } case PREFIX_INCREMENT: case PREFIX_DECREMENT: if (operandType->isScalar()) { return operandType; } else { return tree().makeErroneousType(); } break; default: unreachable(); break; } return NULL; }
static void makeAsmTag ( const vString *const name, const vString *const operator, const bool labelCandidate, const bool nameFollows, const bool directive, unsigned int *lastMacroCorkIndex) { if (vStringLength (name) > 0) { bool found; const AsmKind kind = operatorKind (operator, &found); if (found) { if (kind > K_NONE) makeSimpleTag (name, kind); } else if (isDefineOperator (operator)) { if (! nameFollows) makeSimpleTag (name, K_DEFINE); } else if (labelCandidate) { operatorKind (name, &found); if (! found) makeSimpleTag (name, K_LABEL); } else if (directive) { bool found_dummy; const AsmKind kind_for_directive = operatorKind (name, &found_dummy); tagEntryInfo *macro_tag; switch (kind_for_directive) { case K_NONE: break; case K_MACRO: *lastMacroCorkIndex = makeSimpleTag (operator, kind_for_directive); break; case K_PSUEDO_MACRO_END: if (*lastMacroCorkIndex != CORK_NIL) { macro_tag = getEntryInCorkQueue (*lastMacroCorkIndex); macro_tag->extensionFields.endLine = getInputLineNumber (); *lastMacroCorkIndex = CORK_NIL; } break; case K_SECTION: makeSimpleRefTag (operator, kind_for_directive, ASM_SECTION_PLACEMENT); break; default: makeSimpleTag (operator, kind_for_directive); } } } }