Add support for operators on Core.IntLiteral. (#4716)

Fixes integer builtins to produce the correct values (and not
CHECK-fail) when used on integer literals. Also adds impls to the
prelude to use the new builtins to perform operations on integer
literals.

Perhaps most importantly, this allows directly initializing `i32` values
with negative numbers, as the negation operation on integer literals now
works.

For testing I've added tests for use of literals with one operator in
each class (addition, multiplication, ordering, bitwise, etc) for which
there are distinct rules or overflow behavior, rather than exhaustively
testing all the combinations. This is aimed at finding a good tradeoff
between maintainability of the tests and thorough test coverage.

Also fixes lowering of heterogeneous shifts and comparisons. These are
currently disabled when one of the operands is an integer literal, but
we may want to allow that when the integer literal operand has a known
constant value.
This commit is contained in:
Richard Smith
2024-12-31 06:36:43 +00:00
committed by GitHub
parent 624950c62c
commit 4a7aefefaa
59 changed files with 1839 additions and 420 deletions
+8 -3
View File
@@ -48,6 +48,11 @@ class ConstantContext {
return nullptr;
}
// Gets the value to use for an integer literal.
auto GetIntLiteralAsValue() const -> llvm::Constant* {
return file_context_->GetIntLiteralAsValue();
}
// Gets a callable's function. Returns nullptr for a builtin.
auto GetFunction(SemIR::FunctionId function_id) -> llvm::Function* {
return file_context_->GetFunction(function_id);
@@ -187,9 +192,9 @@ static auto EmitAsConstant(ConstantContext& context, SemIR::IntValue inst)
// represented as an LLVM integer type.
auto* int_type = llvm::dyn_cast<llvm::IntegerType>(type);
if (!int_type) {
auto* struct_type = llvm::dyn_cast<llvm::StructType>(type);
CARBON_CHECK(struct_type && struct_type->getNumElements() == 0);
return llvm::ConstantStruct::get(struct_type);
auto* int_literal_value = context.GetIntLiteralAsValue();
CARBON_CHECK(int_literal_value->getType() == type);
return int_literal_value;
}
auto val = context.sem_ir().ints().Get(inst.int_id);