diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-02-26 22:19:53 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-26 22:19:53 +0000 |
| commit | 46fd5fe81860ee6bd803f836ae78ceb9dc73ccae (patch) | |
| tree | 867f20002dcbc19ebf32c45b41e13a19b8e31db7 /source/slang | |
| parent | 7bce066cfc51296a538c7a7d325133d60e352494 (diff) | |
Fix for GCC C++ target - remove warning for int literal value. (#1244)
* Fix for GCC C++ target - remove warning for int literal value.
* Comment around hack to negate -0x8000 0000
* Special case negation of literals in parser - to fix problems with errors on gcc.
* Apply the literal integer 'fix' when doing negation of a literal.
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-emit-c-like.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 135 |
2 files changed, 95 insertions, 48 deletions
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 5f784cba3..538ef369a 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -783,8 +783,14 @@ void CLikeSourceEmitter::emitSimpleValueImpl(IRInst* inst) // Why having a cast or having a suffix would make a difference though is not clear. It is also possible that the // L suffix is just ignored, and the literal is really a 'non typed' int literal in C++. + // This little hack is needed for gcc that if we have the expression + // int(-0x80000000) we get the warning: warning : integer overflow in expression [-Woverflow] + // 0x80000000 and -0x80000000 mean the same thing when casted to 32 bit int, so we just flip the value here. + IRIntegerValue value = litInst->value.intVal; + value = (value == -0x80000000ll) ? -value : value; + m_writer->emit("int("); - m_writer->emit(litInst->value.intVal); + m_writer->emit(value); m_writer->emit(")"); return; } diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 288962cd8..7a9d8d447 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -4010,6 +4010,57 @@ namespace Slang return FloatFixKind::None; } + static IntegerLiteralValue _fixIntegerLiteral(BaseType baseType, IntegerLiteralValue value, Token* token, DiagnosticSink* sink) + { + // TODO(JS): + // It is worth noting here that because of the way that the lexer works, that literals + // are always handled as if they are positive (a preceding - is taken as a negate on a + // positive value). + // The code here is designed to work with positive and negative values, as this behavior + // might change in the future, and is arguably more 'correct'. + + const BaseTypeInfo& info = BaseTypeInfo::getInfo(baseType); + SLANG_ASSERT(info.flags & BaseTypeInfo::Flag::Integer); + SLANG_COMPILE_TIME_ASSERT(sizeof(value) == sizeof(uint64_t)); + + // If the type is 64 bits, do nothing, we'll assume all is good + if (baseType != BaseType::Void && info.sizeInBytes != sizeof(value)) + { + const IntegerLiteralValue signBit = IntegerLiteralValue(1) << (8 * info.sizeInBytes - 1); + // Same as (~IntegerLiteralValue(0)) << (8 * info.sizeInBytes);, without the need for variable shift + const IntegerLiteralValue mask = -(signBit + signBit); + + IntegerLiteralValue truncatedValue = value; + // If it's signed, and top bit is set, sign extend it negative + if (info.flags & BaseTypeInfo::Flag::Signed) + { + // Sign extend + truncatedValue = (value & signBit) ? (value | mask) : (value & ~mask); + } + else + { + // 0 top bits + truncatedValue = value & ~mask; + } + + const IntegerLiteralValue maskedValue = value & mask; + + // If the masked value is 0 or equal to the mask, we 'assume' no information is + // lost + // This allows for example -1u, to give 0xffffffff + // It also means 0xfffffffffffffffffu will give 0xffffffff, without a warning. + if ((!(maskedValue == 0 || maskedValue == mask)) && sink && token) + { + // Output a warning that number has been altered + sink->diagnose(*token, Diagnostics::integerLiteralTruncated, token->Content, BaseTypeInfo::asText(baseType), truncatedValue); + } + + value = truncatedValue; + } + + return value; + } + static RefPtr<Expr> parseAtomicExpr(Parser* parser) { switch( peekTokenType(parser) ) @@ -4162,52 +4213,8 @@ namespace Slang } } - // TODO(JS): - // It is worth noting here that because of the way that the lexer works, that literals - // are always handled as if they are positive (a preceding - is taken as a negate on a - // positive value). - // The code here is designed to work with positive and negative values, as this behavior - // might change in the future, and is arguably more 'correct'. - - const BaseTypeInfo& info = BaseTypeInfo::getInfo(suffixBaseType); - SLANG_ASSERT(info.flags & BaseTypeInfo::Flag::Integer); - SLANG_COMPILE_TIME_ASSERT(sizeof(value) == sizeof(uint64_t)); - - // If the type is 64 bits, do nothing, we'll assume all is good - if (suffixBaseType != BaseType::Void && info.sizeInBytes != sizeof(value)) - { - const IntegerLiteralValue signBit = IntegerLiteralValue(1) << (8 * info.sizeInBytes - 1); - // Same as (~IntegerLiteralValue(0)) << (8 * info.sizeInBytes);, without the need for variable shift - const IntegerLiteralValue mask = -(signBit + signBit); - - IntegerLiteralValue truncatedValue = value; - // If it's signed, and top bit is set, sign extend it negative - if (info.flags & BaseTypeInfo::Flag::Signed) - { - // Sign extend - truncatedValue = (value & signBit) ? (value | mask) : (value & ~mask); - } - else - { - // 0 top bits - truncatedValue = value & ~mask; - } - - const IntegerLiteralValue maskedValue = value & mask; - - // If the masked value is 0 or equal to the mask, we 'assume' no information is - // lost - // This allows for example -1u, to give 0xffffffff - // It also means 0xfffffffffffffffffu will give 0xffffffff, without a warning. - if (!(maskedValue == 0 || maskedValue == mask)) - { - // Output a warning that number has been altered - parser->sink->diagnose(token, Diagnostics::integerLiteralTruncated, token.Content, BaseTypeInfo::asText(suffixBaseType), truncatedValue); - } - - value = truncatedValue; - } - + value = _fixIntegerLiteral(suffixBaseType, value, &token, parser->sink); + auto session = parser->getSession(); Type* suffixType = (suffixBaseType == BaseType::Void) ? session->getErrorType() : session->getBuiltinType(suffixBaseType); @@ -4514,7 +4521,6 @@ namespace Slang case TokenType::OpNot: case TokenType::OpBitNot: case TokenType::OpAdd: - case TokenType::OpSub: { RefPtr<PrefixExpr> prefixExpr = new PrefixExpr(); parser->FillPosition(prefixExpr.Ptr()); @@ -4522,6 +4528,41 @@ namespace Slang prefixExpr->Arguments.add(parsePrefixExpr(parser)); return prefixExpr; } + case TokenType::OpSub: + { + // Special case prefix sub (aka neg), so if it's on a literal, it produces a new literal + + RefPtr<PrefixExpr> prefixExpr = new PrefixExpr(); + parser->FillPosition(prefixExpr.Ptr()); + prefixExpr->FunctionExpr = parseOperator(parser); + + auto arg = parsePrefixExpr(parser); + + if (auto intLit = as<IntegerLiteralExpr>(arg)) + { + RefPtr<IntegerLiteralExpr> newLiteral = new IntegerLiteralExpr(*intLit); + + IRIntegerValue value = -newLiteral->value; + + // Need to get the basic type, so we can fit to underlying type + if (auto basicExprType = as<BasicExpressionType>(intLit->type.type)) + { + value = _fixIntegerLiteral(basicExprType->baseType, value, nullptr, nullptr); + } + + newLiteral->value = value; + return newLiteral; + } + else if (auto floatLit = as<FloatingPointLiteralExpr>(arg)) + { + RefPtr<FloatingPointLiteralExpr> newLiteral = new FloatingPointLiteralExpr(*floatLit); + newLiteral->value = -newLiteral->value; + return newLiteral; + } + + prefixExpr->Arguments.add(arg); + return prefixExpr; + } break; } } |
