Add builtins for integer bitwise, bit-shift, and relational comparison operators. (#3853)

This commit is contained in:
Richard Smith
2024-04-03 22:21:55 +00:00
committed by GitHub
parent 11c56d8ca1
commit 762d07fa3e
27 changed files with 2367 additions and 234 deletions
+1
View File
@@ -7,6 +7,7 @@ circularly
compiletime
copyable
crate
createor
crossreference
falsy
forin
+112 -30
View File
@@ -74,6 +74,22 @@ static auto MakeNonConstantResult(Phase phase) -> SemIR::ConstantId {
: SemIR::ConstantId::NotConstant;
}
// Converts a bool value into a ConstantId.
static auto MakeBoolResult(Context& context, SemIR::TypeId bool_type_id,
bool result) -> SemIR::ConstantId {
return MakeConstantResult(
context, SemIR::BoolLiteral{bool_type_id, SemIR::BoolValue::From(result)},
Phase::Template);
}
// Converts an APInt value into a ConstantId.
static auto MakeIntResult(Context& context, SemIR::TypeId type_id,
llvm::APInt value) -> SemIR::ConstantId {
auto result = context.ints().Add(std::move(value));
return MakeConstantResult(context, SemIR::IntLiteral{type_id, result},
Phase::Template);
}
// `GetConstantValue` checks to see whether the provided ID describes a value
// with constant phase, and if so, returns the corresponding constant value.
// Overloads are provided for different kinds of ID.
@@ -297,23 +313,28 @@ static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
SemIR::BuiltinFunctionKind builtin_kind,
SemIR::InstId arg_id)
-> SemIR::ConstantId {
CARBON_CHECK(builtin_kind == SemIR::BuiltinFunctionKind::IntNegate)
<< "Unexpected builtin kind";
auto op = context.insts().GetAs<SemIR::IntLiteral>(arg_id);
auto op_val = context.ints().Get(op.int_id);
if (context.types().IsSignedInt(op.type_id) && op_val.isMinSignedValue()) {
CARBON_DIAGNOSTIC(CompileTimeIntegerNegateOverflow, Error,
"Integer overflow in negation of {0}.", TypedInt);
context.emitter().Emit(loc, CompileTimeIntegerNegateOverflow,
TypedInt{op.type_id, op_val});
switch (builtin_kind) {
case SemIR::BuiltinFunctionKind::IntNegate:
if (context.types().IsSignedInt(op.type_id) &&
op_val.isMinSignedValue()) {
CARBON_DIAGNOSTIC(CompileTimeIntegerNegateOverflow, Error,
"Integer overflow in negation of {0}.", TypedInt);
context.emitter().Emit(loc, CompileTimeIntegerNegateOverflow,
TypedInt{op.type_id, op_val});
}
op_val.negate();
break;
case SemIR::BuiltinFunctionKind::IntComplement:
op_val.flipAllBits();
break;
default:
CARBON_FATAL() << "Unexpected builtin kind";
}
op_val.negate();
auto result = context.ints().Add(op_val);
return MakeConstantResult(context, SemIR::IntLiteral{op.type_id, result},
Phase::Template);
return MakeIntResult(context, op.type_id, std::move(op_val));
}
// Performs a builtin binary integer -> integer operation.
@@ -324,14 +345,15 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
-> SemIR::ConstantId {
auto lhs = context.insts().GetAs<SemIR::IntLiteral>(lhs_id);
auto rhs = context.insts().GetAs<SemIR::IntLiteral>(rhs_id);
auto lhs_val = context.ints().Get(lhs.int_id);
auto rhs_val = context.ints().Get(rhs.int_id);
const auto& lhs_val = context.ints().Get(lhs.int_id);
const auto& rhs_val = context.ints().Get(rhs.int_id);
bool is_signed = context.types().IsSignedInt(lhs.type_id);
bool overflow = false;
llvm::APInt result_val;
llvm::StringLiteral op_str = "<error>";
switch (builtin_kind) {
// Arithmetic.
case SemIR::BuiltinFunctionKind::IntAdd:
result_val =
is_signed ? lhs_val.sadd_ov(rhs_val, overflow) : lhs_val + rhs_val;
@@ -368,6 +390,49 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
op_str = "%";
break;
// Bitwise.
case SemIR::BuiltinFunctionKind::IntAnd:
result_val = lhs_val & rhs_val;
op_str = "&";
break;
case SemIR::BuiltinFunctionKind::IntOr:
result_val = lhs_val | rhs_val;
op_str = "|";
break;
case SemIR::BuiltinFunctionKind::IntXor:
result_val = lhs_val ^ rhs_val;
op_str = "^";
break;
// Bit shift.
case SemIR::BuiltinFunctionKind::IntLeftShift:
case SemIR::BuiltinFunctionKind::IntRightShift:
op_str = (builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift)
? llvm::StringLiteral("<<")
: llvm::StringLiteral(">>");
if (rhs_val.uge(lhs_val.getBitWidth()) ||
(rhs_val.isNegative() && context.types().IsSignedInt(rhs.type_id))) {
CARBON_DIAGNOSTIC(
CompileTimeShiftOutOfRange, Error,
"Shift distance not in range [0, {0}) in {1} {2} {3}.", unsigned,
TypedInt, llvm::StringLiteral, TypedInt);
context.emitter().Emit(loc, CompileTimeShiftOutOfRange,
lhs_val.getBitWidth(),
TypedInt{lhs.type_id, lhs_val}, op_str,
TypedInt{rhs.type_id, rhs_val});
// TODO: Is it useful to recover by returning 0 or -1?
return SemIR::ConstantId::Error;
}
if (builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift) {
result_val = lhs_val.shl(rhs_val);
} else if (is_signed) {
result_val = lhs_val.ashr(rhs_val);
} else {
result_val = lhs_val.lshr(rhs_val);
}
break;
default:
CARBON_FATAL() << "Unexpected operation kind.";
}
@@ -381,9 +446,7 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
TypedInt{rhs.type_id, rhs_val});
}
auto result = context.ints().Add(result_val);
return MakeConstantResult(context, SemIR::IntLiteral{lhs.type_id, result},
Phase::Template);
return MakeIntResult(context, lhs.type_id, std::move(result_val));
}
// Performs a builtin integer comparison.
@@ -393,10 +456,11 @@ static auto PerformBuiltinIntComparison(Context& context,
SemIR::InstId rhs_id,
SemIR::TypeId bool_type_id)
-> SemIR::ConstantId {
auto lhs_val = context.ints().Get(
context.insts().GetAs<SemIR::IntLiteral>(lhs_id).int_id);
auto rhs_val = context.ints().Get(
auto lhs = context.insts().GetAs<SemIR::IntLiteral>(lhs_id);
const auto& lhs_val = context.ints().Get(lhs.int_id);
const auto& rhs_val = context.ints().Get(
context.insts().GetAs<SemIR::IntLiteral>(rhs_id).int_id);
bool is_signed = context.types().IsSignedInt(lhs.type_id);
bool result;
switch (builtin_kind) {
@@ -406,13 +470,23 @@ static auto PerformBuiltinIntComparison(Context& context,
case SemIR::BuiltinFunctionKind::IntNeq:
result = (lhs_val != rhs_val);
break;
case SemIR::BuiltinFunctionKind::IntLess:
result = is_signed ? lhs_val.slt(rhs_val) : lhs_val.ult(rhs_val);
break;
case SemIR::BuiltinFunctionKind::IntLessEq:
result = is_signed ? lhs_val.sle(rhs_val) : lhs_val.ule(rhs_val);
break;
case SemIR::BuiltinFunctionKind::IntGreater:
result = is_signed ? lhs_val.sgt(rhs_val) : lhs_val.sgt(rhs_val);
break;
case SemIR::BuiltinFunctionKind::IntGreaterEq:
result = is_signed ? lhs_val.sge(rhs_val) : lhs_val.sge(rhs_val);
break;
default:
CARBON_FATAL() << "Unexpected operation kind.";
}
return MakeConstantResult(
context, SemIR::BoolLiteral{bool_type_id, SemIR::BoolValue::From(result)},
Phase::Template);
return MakeBoolResult(context, bool_type_id, result);
}
static auto PerformBuiltinCall(Context& context, SemIRLoc loc, SemIR::Call call,
@@ -424,20 +498,25 @@ static auto PerformBuiltinCall(Context& context, SemIRLoc loc, SemIR::Call call,
CARBON_FATAL() << "Not a builtin function.";
// Unary integer -> integer operations.
case SemIR::BuiltinFunctionKind::IntNegate: {
// TODO: Complement.
case SemIR::BuiltinFunctionKind::IntNegate:
case SemIR::BuiltinFunctionKind::IntComplement: {
if (phase != Phase::Template) {
break;
}
return PerformBuiltinUnaryIntOp(context, loc, builtin_kind, arg_ids[0]);
}
// Homogeneous binary integer -> integer operations.
// Binary integer -> integer operations.
case SemIR::BuiltinFunctionKind::IntAdd:
case SemIR::BuiltinFunctionKind::IntSub:
case SemIR::BuiltinFunctionKind::IntMul:
case SemIR::BuiltinFunctionKind::IntDiv:
case SemIR::BuiltinFunctionKind::IntMod: {
case SemIR::BuiltinFunctionKind::IntMod:
case SemIR::BuiltinFunctionKind::IntAnd:
case SemIR::BuiltinFunctionKind::IntOr:
case SemIR::BuiltinFunctionKind::IntXor:
case SemIR::BuiltinFunctionKind::IntLeftShift:
case SemIR::BuiltinFunctionKind::IntRightShift: {
// TODO: Bitwise operators.
if (phase != Phase::Template) {
break;
@@ -448,7 +527,11 @@ static auto PerformBuiltinCall(Context& context, SemIRLoc loc, SemIR::Call call,
// Integer comparisons.
case SemIR::BuiltinFunctionKind::IntEq:
case SemIR::BuiltinFunctionKind::IntNeq: {
case SemIR::BuiltinFunctionKind::IntNeq:
case SemIR::BuiltinFunctionKind::IntLess:
case SemIR::BuiltinFunctionKind::IntLessEq:
case SemIR::BuiltinFunctionKind::IntGreater:
case SemIR::BuiltinFunctionKind::IntGreaterEq: {
// TODO: Relational comparisons.
if (phase != Phase::Template) {
break;
@@ -696,8 +779,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
if (phase == Phase::Template) {
auto value =
context.insts().GetAs<SemIR::BoolLiteral>(const_id.inst_id());
value.value = SemIR::BoolValue::From(!value.value.ToBool());
return MakeConstantResult(context, value, Phase::Template);
return MakeBoolResult(context, value.type_id, !value.value.ToBool());
}
if (phase == Phase::UnknownDueToError) {
return SemIR::ConstantId::Error;
+75
View File
@@ -0,0 +1,75 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_and.carbon
fn And(a: i32, b: i32) -> i32 = "int.and";
var arr: [i32; And(12, 10)];
let arr_p: [i32; 8]* = &arr;
fn RuntimeCall(a: i32, b: i32) -> i32 {
return And(a, b);
}
// CHECK:STDOUT: --- int_and.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 12 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 10 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 8 [template]
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
// CHECK:STDOUT: %.5: type = ptr_type [i32; 8] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .And = %And
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %And: <function> = fn_decl @And [template] {
// CHECK:STDOUT: %a.loc2_8.1: i32 = param a
// CHECK:STDOUT: @And.%a: i32 = bind_name a, %a.loc2_8.1
// CHECK:STDOUT: %b.loc2_16.1: i32 = param b
// CHECK:STDOUT: @And.%b: i32 = bind_name b, %b.loc2_16.1
// CHECK:STDOUT: %return.var.loc2: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %And.ref: <function> = name_ref And, %And [template = %And]
// CHECK:STDOUT: %.loc4_20: i32 = int_literal 12 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_24: i32 = int_literal 10 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_19: init i32 = call %And.ref(%.loc4_20, %.loc4_24) [template = constants.%.3]
// CHECK:STDOUT: %.loc4_27: type = array_type %.loc4_19, i32 [template = constants.%.4]
// CHECK:STDOUT: %arr.var: ref [i32; 8] = var arr
// CHECK:STDOUT: %arr: ref [i32; 8] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 8 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_20: type = ptr_type [i32; 8] [template = constants.%.5]
// CHECK:STDOUT: %arr.ref: ref [i32; 8] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_24: [i32; 8]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 8]* = bind_name arr_p, %.loc5_24
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @And(%a: i32, %b: i32) -> i32 = "int.and";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %And.ref: <function> = name_ref And, file.%And [template = file.%And]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc8_13.1: init i32 = call %And.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_19: i32 = value_of_initializer %.loc8_13.1
// CHECK:STDOUT: %.loc8_13.2: i32 = converted %.loc8_13.1, %.loc8_19
// CHECK:STDOUT: return %.loc8_13.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+86
View File
@@ -0,0 +1,86 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_complement.carbon
fn Complement(a: i32) -> i32 = "int.complement";
fn And(a: i32, b: i32) -> i32 = "int.and";
var arr: [i32; And(Complement(0x123456), 0xFFFFFF)];
let arr_p: [i32; 0xEDCBA9]* = &arr;
fn RuntimeCall(a: i32) -> i32 {
return Complement(a);
}
// CHECK:STDOUT: --- int_complement.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1193046 [template]
// CHECK:STDOUT: %.2: i32 = int_literal -1193047 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 16777215 [template]
// CHECK:STDOUT: %.4: i32 = int_literal 15584169 [template]
// CHECK:STDOUT: %.5: type = array_type %.4, i32 [template]
// CHECK:STDOUT: %.6: type = ptr_type [i32; 15584169] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Complement = %Complement
// CHECK:STDOUT: .And = %And
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Complement: <function> = fn_decl @Complement [template] {
// CHECK:STDOUT: %a.loc2_15.1: i32 = param a
// CHECK:STDOUT: @Complement.%a: i32 = bind_name a, %a.loc2_15.1
// CHECK:STDOUT: %return.var.loc2: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %And: <function> = fn_decl @And [template] {
// CHECK:STDOUT: %a.loc3_8.1: i32 = param a
// CHECK:STDOUT: @And.%a: i32 = bind_name a, %a.loc3_8.1
// CHECK:STDOUT: %b.loc3_16.1: i32 = param b
// CHECK:STDOUT: @And.%b: i32 = bind_name b, %b.loc3_16.1
// CHECK:STDOUT: %return.var.loc3: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %And.ref: <function> = name_ref And, %And [template = %And]
// CHECK:STDOUT: %Complement.ref: <function> = name_ref Complement, %Complement [template = %Complement]
// CHECK:STDOUT: %.loc5_31: i32 = int_literal 1193046 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_30.1: init i32 = call %Complement.ref(%.loc5_31) [template = constants.%.2]
// CHECK:STDOUT: %.loc5_42: i32 = int_literal 16777215 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_19.1: i32 = value_of_initializer %.loc5_30.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc5_30.2: i32 = converted %.loc5_30.1, %.loc5_19.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc5_19.2: init i32 = call %And.ref(%.loc5_30.2, %.loc5_42) [template = constants.%.4]
// CHECK:STDOUT: %.loc5_51: type = array_type %.loc5_19.2, i32 [template = constants.%.5]
// CHECK:STDOUT: %arr.var: ref [i32; 15584169] = var arr
// CHECK:STDOUT: %arr: ref [i32; 15584169] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc6_18: i32 = int_literal 15584169 [template = constants.%.4]
// CHECK:STDOUT: %.loc6_26: type = array_type %.loc6_18, i32 [template = constants.%.5]
// CHECK:STDOUT: %.loc6_27: type = ptr_type [i32; 15584169] [template = constants.%.6]
// CHECK:STDOUT: %arr.ref: ref [i32; 15584169] = name_ref arr, %arr
// CHECK:STDOUT: %.loc6_31: [i32; 15584169]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 15584169]* = bind_name arr_p, %.loc6_31
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc8_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc8_16.1
// CHECK:STDOUT: %return.var.loc8: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Complement(%a: i32) -> i32 = "int.complement";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @And(%a: i32, %b: i32) -> i32 = "int.and";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32) -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Complement.ref: <function> = name_ref Complement, file.%Complement [template = file.%Complement]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %.loc9_20.1: init i32 = call %Complement.ref(%a.ref)
// CHECK:STDOUT: %.loc9_23: i32 = value_of_initializer %.loc9_20.1
// CHECK:STDOUT: %.loc9_20.2: i32 = converted %.loc9_20.1, %.loc9_23
// CHECK:STDOUT: return %.loc9_20.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+162
View File
@@ -0,0 +1,162 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_eq.carbon
fn Eq(a: i32, b: i32) -> bool = "int.eq";
class True {}
class False {}
fn F(true_: True, false_: False) {
true_ as (if Eq(1, 1) then True else False);
false_ as (if Eq(1, 2) then True else False);
}
fn RuntimeCall(a: i32, b: i32) -> bool {
return Eq(a, b);
}
// --- fail_bad_decl.carbon
package FailBadDecl api;
// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+3]]:1: ERROR: Invalid signature for builtin function "int.eq".
// CHECK:STDERR: fn WrongResult(a: i32, b: i32) -> i32 = "int.eq";
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fn WrongResult(a: i32, b: i32) -> i32 = "int.eq";
// CHECK:STDOUT: --- int_eq.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %True: type = class_type @True [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %False: type = class_type @False [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: bool = bool_literal true [template]
// CHECK:STDOUT: %.6: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.7: bool = bool_literal false [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Eq = %Eq
// CHECK:STDOUT: .True = %True.decl
// CHECK:STDOUT: .False = %False.decl
// CHECK:STDOUT: .F = %F
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Eq: <function> = fn_decl @Eq [template] {
// CHECK:STDOUT: %a.loc2_7.1: i32 = param a
// CHECK:STDOUT: @Eq.%a: i32 = bind_name a, %a.loc2_7.1
// CHECK:STDOUT: %b.loc2_15.1: i32 = param b
// CHECK:STDOUT: @Eq.%b: i32 = bind_name b, %b.loc2_15.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %True.decl: type = class_decl @True [template = constants.%True] {}
// CHECK:STDOUT: %False.decl: type = class_decl @False [template = constants.%False] {}
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
// CHECK:STDOUT: %True.ref: type = name_ref True, %True.decl [template = constants.%True]
// CHECK:STDOUT: %true_.loc7_6.1: True = param true_
// CHECK:STDOUT: @F.%true_: True = bind_name true_, %true_.loc7_6.1
// CHECK:STDOUT: %False.ref: type = name_ref False, %False.decl [template = constants.%False]
// CHECK:STDOUT: %false_.loc7_19.1: False = param false_
// CHECK:STDOUT: @F.%false_: False = bind_name false_, %false_.loc7_19.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc12_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc12_16.1
// CHECK:STDOUT: %b.loc12_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc12_24.1
// CHECK:STDOUT: %return.var.loc12: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @True {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%True
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @False {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%False
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Eq(%a: i32, %b: i32) -> bool = "int.eq";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%true_: True, %false_: False) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %true_.ref: True = name_ref true_, %true_
// CHECK:STDOUT: %Eq.ref.loc8: <function> = name_ref Eq, file.%Eq [template = file.%Eq]
// CHECK:STDOUT: %.loc8_19: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc8_22: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc8_18.1: init bool = call %Eq.ref.loc8(%.loc8_19, %.loc8_22) [template = constants.%.5]
// CHECK:STDOUT: %.loc8_13.1: bool = value_of_initializer %.loc8_18.1 [template = constants.%.5]
// CHECK:STDOUT: %.loc8_18.2: bool = converted %.loc8_18.1, %.loc8_13.1 [template = constants.%.5]
// CHECK:STDOUT: if %.loc8_18.2 br !if.expr.then.loc8 else br !if.expr.else.loc8
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc8:
// CHECK:STDOUT: %True.ref.loc8: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc8(%True.ref.loc8)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc8:
// CHECK:STDOUT: %False.ref.loc8: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc8(%False.ref.loc8)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc8:
// CHECK:STDOUT: %.loc8_13.2: type = block_arg !if.expr.result.loc8 [template = constants.%True]
// CHECK:STDOUT: %false_.ref: False = name_ref false_, %false_
// CHECK:STDOUT: %Eq.ref.loc9: <function> = name_ref Eq, file.%Eq [template = file.%Eq]
// CHECK:STDOUT: %.loc9_20: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc9_23: i32 = int_literal 2 [template = constants.%.6]
// CHECK:STDOUT: %.loc9_19.1: init bool = call %Eq.ref.loc9(%.loc9_20, %.loc9_23) [template = constants.%.7]
// CHECK:STDOUT: %.loc9_14.1: bool = value_of_initializer %.loc9_19.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc9_19.2: bool = converted %.loc9_19.1, %.loc9_14.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc9_19.2 br !if.expr.then.loc9 else br !if.expr.else.loc9
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc9:
// CHECK:STDOUT: %True.ref.loc9: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc9(%True.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc9:
// CHECK:STDOUT: %False.ref.loc9: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc9(%False.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc9:
// CHECK:STDOUT: %.loc9_14.2: type = block_arg !if.expr.result.loc9 [template = constants.%False]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Eq.ref: <function> = name_ref Eq, file.%Eq [template = file.%Eq]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc13_12.1: init bool = call %Eq.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc13_18: bool = value_of_initializer %.loc13_12.1
// CHECK:STDOUT: %.loc13_12.2: bool = converted %.loc13_12.1, %.loc13_18
// CHECK:STDOUT: return %.loc13_12.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_bad_decl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .WrongResult = %WrongResult
// CHECK:STDOUT: }
// CHECK:STDOUT: %WrongResult: <function> = fn_decl @WrongResult [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @WrongResult.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @WrongResult.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @WrongResult(%a: i32, %b: i32) -> i32;
// CHECK:STDOUT:
+215
View File
@@ -0,0 +1,215 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_greater.carbon
fn Greater(a: i32, b: i32) -> bool = "int.greater";
fn Negate(a: i32) -> i32 = "int.negate";
class True {}
class False {}
fn F(true_: True, false_: False) {
false_ as (if Greater(1, 2) then True else False);
false_ as (if Greater(1, 1) then True else False);
true_ as (if Greater(1, 0) then True else False);
false_ as (if Greater(Negate(1), 0) then True else False);
true_ as (if Greater(0, Negate(1)) then True else False);
}
fn RuntimeCall(a: i32, b: i32) -> bool {
return Greater(a, b);
}
// CHECK:STDOUT: --- int_greater.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %True: type = class_type @True [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %False: type = class_type @False [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.6: bool = bool_literal false [template]
// CHECK:STDOUT: %.7: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.8: bool = bool_literal true [template]
// CHECK:STDOUT: %.9: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Greater = %Greater
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: .True = %True.decl
// CHECK:STDOUT: .False = %False.decl
// CHECK:STDOUT: .F = %F
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Greater: <function> = fn_decl @Greater [template] {
// CHECK:STDOUT: %a.loc2_12.1: i32 = param a
// CHECK:STDOUT: @Greater.%a: i32 = bind_name a, %a.loc2_12.1
// CHECK:STDOUT: %b.loc2_20.1: i32 = param b
// CHECK:STDOUT: @Greater.%b: i32 = bind_name b, %b.loc2_20.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc3_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc3_11.1
// CHECK:STDOUT: %return.var.loc3: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %True.decl: type = class_decl @True [template = constants.%True] {}
// CHECK:STDOUT: %False.decl: type = class_decl @False [template = constants.%False] {}
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
// CHECK:STDOUT: %True.ref: type = name_ref True, %True.decl [template = constants.%True]
// CHECK:STDOUT: %true_.loc8_6.1: True = param true_
// CHECK:STDOUT: @F.%true_: True = bind_name true_, %true_.loc8_6.1
// CHECK:STDOUT: %False.ref: type = name_ref False, %False.decl [template = constants.%False]
// CHECK:STDOUT: %false_.loc8_19.1: False = param false_
// CHECK:STDOUT: @F.%false_: False = bind_name false_, %false_.loc8_19.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc16_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc16_16.1
// CHECK:STDOUT: %b.loc16_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc16_24.1
// CHECK:STDOUT: %return.var.loc16: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @True {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%True
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @False {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%False
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Greater(%a: i32, %b: i32) -> bool = "int.greater";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%true_: True, %false_: False) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %false_.ref.loc9: False = name_ref false_, %false_
// CHECK:STDOUT: %Greater.ref.loc9: <function> = name_ref Greater, file.%Greater [template = file.%Greater]
// CHECK:STDOUT: %.loc9_25: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc9_28: i32 = int_literal 2 [template = constants.%.5]
// CHECK:STDOUT: %.loc9_24.1: init bool = call %Greater.ref.loc9(%.loc9_25, %.loc9_28) [template = constants.%.6]
// CHECK:STDOUT: %.loc9_14.1: bool = value_of_initializer %.loc9_24.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc9_24.2: bool = converted %.loc9_24.1, %.loc9_14.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc9_24.2 br !if.expr.then.loc9 else br !if.expr.else.loc9
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc9:
// CHECK:STDOUT: %True.ref.loc9: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc9(%True.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc9:
// CHECK:STDOUT: %False.ref.loc9: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc9(%False.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc9:
// CHECK:STDOUT: %.loc9_14.2: type = block_arg !if.expr.result.loc9 [template = constants.%False]
// CHECK:STDOUT: %false_.ref.loc10: False = name_ref false_, %false_
// CHECK:STDOUT: %Greater.ref.loc10: <function> = name_ref Greater, file.%Greater [template = file.%Greater]
// CHECK:STDOUT: %.loc10_25: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_28: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_24.1: init bool = call %Greater.ref.loc10(%.loc10_25, %.loc10_28) [template = constants.%.6]
// CHECK:STDOUT: %.loc10_14.1: bool = value_of_initializer %.loc10_24.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc10_24.2: bool = converted %.loc10_24.1, %.loc10_14.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc10_24.2 br !if.expr.then.loc10 else br !if.expr.else.loc10
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc10:
// CHECK:STDOUT: %True.ref.loc10: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc10(%True.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc10:
// CHECK:STDOUT: %False.ref.loc10: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc10(%False.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc10:
// CHECK:STDOUT: %.loc10_14.2: type = block_arg !if.expr.result.loc10 [template = constants.%False]
// CHECK:STDOUT: %true_.ref.loc11: True = name_ref true_, %true_
// CHECK:STDOUT: %Greater.ref.loc11: <function> = name_ref Greater, file.%Greater [template = file.%Greater]
// CHECK:STDOUT: %.loc11_24: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc11_27: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %.loc11_23.1: init bool = call %Greater.ref.loc11(%.loc11_24, %.loc11_27) [template = constants.%.8]
// CHECK:STDOUT: %.loc11_13.1: bool = value_of_initializer %.loc11_23.1 [template = constants.%.8]
// CHECK:STDOUT: %.loc11_23.2: bool = converted %.loc11_23.1, %.loc11_13.1 [template = constants.%.8]
// CHECK:STDOUT: if %.loc11_23.2 br !if.expr.then.loc11 else br !if.expr.else.loc11
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc11:
// CHECK:STDOUT: %True.ref.loc11: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc11(%True.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc11:
// CHECK:STDOUT: %False.ref.loc11: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc11(%False.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc11:
// CHECK:STDOUT: %.loc11_13.2: type = block_arg !if.expr.result.loc11 [template = constants.%True]
// CHECK:STDOUT: %false_.ref.loc12: False = name_ref false_, %false_
// CHECK:STDOUT: %Greater.ref.loc12: <function> = name_ref Greater, file.%Greater [template = file.%Greater]
// CHECK:STDOUT: %Negate.ref.loc12: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc12_32: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc12_31.1: init i32 = call %Negate.ref.loc12(%.loc12_32) [template = constants.%.9]
// CHECK:STDOUT: %.loc12_36: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %.loc12_24.1: i32 = value_of_initializer %.loc12_31.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_31.2: i32 = converted %.loc12_31.1, %.loc12_24.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_24.2: init bool = call %Greater.ref.loc12(%.loc12_31.2, %.loc12_36) [template = constants.%.6]
// CHECK:STDOUT: %.loc12_14.1: bool = value_of_initializer %.loc12_24.2 [template = constants.%.6]
// CHECK:STDOUT: %.loc12_24.3: bool = converted %.loc12_24.2, %.loc12_14.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc12_24.3 br !if.expr.then.loc12 else br !if.expr.else.loc12
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc12:
// CHECK:STDOUT: %True.ref.loc12: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc12(%True.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc12:
// CHECK:STDOUT: %False.ref.loc12: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc12(%False.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc12:
// CHECK:STDOUT: %.loc12_14.2: type = block_arg !if.expr.result.loc12 [template = constants.%False]
// CHECK:STDOUT: %true_.ref.loc13: True = name_ref true_, %true_
// CHECK:STDOUT: %Greater.ref.loc13: <function> = name_ref Greater, file.%Greater [template = file.%Greater]
// CHECK:STDOUT: %.loc13_24: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %Negate.ref.loc13: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc13_34: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc13_33.1: init i32 = call %Negate.ref.loc13(%.loc13_34) [template = constants.%.9]
// CHECK:STDOUT: %.loc13_23.1: i32 = value_of_initializer %.loc13_33.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_33.2: i32 = converted %.loc13_33.1, %.loc13_23.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_23.2: init bool = call %Greater.ref.loc13(%.loc13_24, %.loc13_33.2) [template = constants.%.8]
// CHECK:STDOUT: %.loc13_13.1: bool = value_of_initializer %.loc13_23.2 [template = constants.%.8]
// CHECK:STDOUT: %.loc13_23.3: bool = converted %.loc13_23.2, %.loc13_13.1 [template = constants.%.8]
// CHECK:STDOUT: if %.loc13_23.3 br !if.expr.then.loc13 else br !if.expr.else.loc13
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc13:
// CHECK:STDOUT: %True.ref.loc13: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc13(%True.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc13:
// CHECK:STDOUT: %False.ref.loc13: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc13(%False.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc13:
// CHECK:STDOUT: %.loc13_13.2: type = block_arg !if.expr.result.loc13 [template = constants.%True]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Greater.ref: <function> = name_ref Greater, file.%Greater [template = file.%Greater]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc17_17.1: init bool = call %Greater.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc17_23: bool = value_of_initializer %.loc17_17.1
// CHECK:STDOUT: %.loc17_17.2: bool = converted %.loc17_17.1, %.loc17_23
// CHECK:STDOUT: return %.loc17_17.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+215
View File
@@ -0,0 +1,215 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_greater_eq.carbon
fn GreaterEq(a: i32, b: i32) -> bool = "int.greater_eq";
fn Negate(a: i32) -> i32 = "int.negate";
class True {}
class False {}
fn F(true_: True, false_: False) {
false_ as (if GreaterEq(1, 2) then True else False);
true_ as (if GreaterEq(1, 1) then True else False);
true_ as (if GreaterEq(1, 0) then True else False);
false_ as (if GreaterEq(Negate(1), 0) then True else False);
true_ as (if GreaterEq(0, Negate(1)) then True else False);
}
fn RuntimeCall(a: i32, b: i32) -> bool {
return GreaterEq(a, b);
}
// CHECK:STDOUT: --- int_greater_eq.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %True: type = class_type @True [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %False: type = class_type @False [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.6: bool = bool_literal false [template]
// CHECK:STDOUT: %.7: bool = bool_literal true [template]
// CHECK:STDOUT: %.8: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.9: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .GreaterEq = %GreaterEq
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: .True = %True.decl
// CHECK:STDOUT: .False = %False.decl
// CHECK:STDOUT: .F = %F
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %GreaterEq: <function> = fn_decl @GreaterEq [template] {
// CHECK:STDOUT: %a.loc2_14.1: i32 = param a
// CHECK:STDOUT: @GreaterEq.%a: i32 = bind_name a, %a.loc2_14.1
// CHECK:STDOUT: %b.loc2_22.1: i32 = param b
// CHECK:STDOUT: @GreaterEq.%b: i32 = bind_name b, %b.loc2_22.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc3_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc3_11.1
// CHECK:STDOUT: %return.var.loc3: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %True.decl: type = class_decl @True [template = constants.%True] {}
// CHECK:STDOUT: %False.decl: type = class_decl @False [template = constants.%False] {}
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
// CHECK:STDOUT: %True.ref: type = name_ref True, %True.decl [template = constants.%True]
// CHECK:STDOUT: %true_.loc8_6.1: True = param true_
// CHECK:STDOUT: @F.%true_: True = bind_name true_, %true_.loc8_6.1
// CHECK:STDOUT: %False.ref: type = name_ref False, %False.decl [template = constants.%False]
// CHECK:STDOUT: %false_.loc8_19.1: False = param false_
// CHECK:STDOUT: @F.%false_: False = bind_name false_, %false_.loc8_19.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc16_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc16_16.1
// CHECK:STDOUT: %b.loc16_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc16_24.1
// CHECK:STDOUT: %return.var.loc16: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @True {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%True
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @False {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%False
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @GreaterEq(%a: i32, %b: i32) -> bool = "int.greater_eq";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%true_: True, %false_: False) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %false_.ref.loc9: False = name_ref false_, %false_
// CHECK:STDOUT: %GreaterEq.ref.loc9: <function> = name_ref GreaterEq, file.%GreaterEq [template = file.%GreaterEq]
// CHECK:STDOUT: %.loc9_27: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc9_30: i32 = int_literal 2 [template = constants.%.5]
// CHECK:STDOUT: %.loc9_26.1: init bool = call %GreaterEq.ref.loc9(%.loc9_27, %.loc9_30) [template = constants.%.6]
// CHECK:STDOUT: %.loc9_14.1: bool = value_of_initializer %.loc9_26.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc9_26.2: bool = converted %.loc9_26.1, %.loc9_14.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc9_26.2 br !if.expr.then.loc9 else br !if.expr.else.loc9
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc9:
// CHECK:STDOUT: %True.ref.loc9: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc9(%True.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc9:
// CHECK:STDOUT: %False.ref.loc9: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc9(%False.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc9:
// CHECK:STDOUT: %.loc9_14.2: type = block_arg !if.expr.result.loc9 [template = constants.%False]
// CHECK:STDOUT: %true_.ref.loc10: True = name_ref true_, %true_
// CHECK:STDOUT: %GreaterEq.ref.loc10: <function> = name_ref GreaterEq, file.%GreaterEq [template = file.%GreaterEq]
// CHECK:STDOUT: %.loc10_26: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_29: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_25.1: init bool = call %GreaterEq.ref.loc10(%.loc10_26, %.loc10_29) [template = constants.%.7]
// CHECK:STDOUT: %.loc10_13.1: bool = value_of_initializer %.loc10_25.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc10_25.2: bool = converted %.loc10_25.1, %.loc10_13.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc10_25.2 br !if.expr.then.loc10 else br !if.expr.else.loc10
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc10:
// CHECK:STDOUT: %True.ref.loc10: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc10(%True.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc10:
// CHECK:STDOUT: %False.ref.loc10: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc10(%False.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc10:
// CHECK:STDOUT: %.loc10_13.2: type = block_arg !if.expr.result.loc10 [template = constants.%True]
// CHECK:STDOUT: %true_.ref.loc11: True = name_ref true_, %true_
// CHECK:STDOUT: %GreaterEq.ref.loc11: <function> = name_ref GreaterEq, file.%GreaterEq [template = file.%GreaterEq]
// CHECK:STDOUT: %.loc11_26: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc11_29: i32 = int_literal 0 [template = constants.%.8]
// CHECK:STDOUT: %.loc11_25.1: init bool = call %GreaterEq.ref.loc11(%.loc11_26, %.loc11_29) [template = constants.%.7]
// CHECK:STDOUT: %.loc11_13.1: bool = value_of_initializer %.loc11_25.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc11_25.2: bool = converted %.loc11_25.1, %.loc11_13.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc11_25.2 br !if.expr.then.loc11 else br !if.expr.else.loc11
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc11:
// CHECK:STDOUT: %True.ref.loc11: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc11(%True.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc11:
// CHECK:STDOUT: %False.ref.loc11: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc11(%False.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc11:
// CHECK:STDOUT: %.loc11_13.2: type = block_arg !if.expr.result.loc11 [template = constants.%True]
// CHECK:STDOUT: %false_.ref.loc12: False = name_ref false_, %false_
// CHECK:STDOUT: %GreaterEq.ref.loc12: <function> = name_ref GreaterEq, file.%GreaterEq [template = file.%GreaterEq]
// CHECK:STDOUT: %Negate.ref.loc12: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc12_34: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc12_33.1: init i32 = call %Negate.ref.loc12(%.loc12_34) [template = constants.%.9]
// CHECK:STDOUT: %.loc12_38: i32 = int_literal 0 [template = constants.%.8]
// CHECK:STDOUT: %.loc12_26.1: i32 = value_of_initializer %.loc12_33.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_33.2: i32 = converted %.loc12_33.1, %.loc12_26.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_26.2: init bool = call %GreaterEq.ref.loc12(%.loc12_33.2, %.loc12_38) [template = constants.%.6]
// CHECK:STDOUT: %.loc12_14.1: bool = value_of_initializer %.loc12_26.2 [template = constants.%.6]
// CHECK:STDOUT: %.loc12_26.3: bool = converted %.loc12_26.2, %.loc12_14.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc12_26.3 br !if.expr.then.loc12 else br !if.expr.else.loc12
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc12:
// CHECK:STDOUT: %True.ref.loc12: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc12(%True.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc12:
// CHECK:STDOUT: %False.ref.loc12: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc12(%False.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc12:
// CHECK:STDOUT: %.loc12_14.2: type = block_arg !if.expr.result.loc12 [template = constants.%False]
// CHECK:STDOUT: %true_.ref.loc13: True = name_ref true_, %true_
// CHECK:STDOUT: %GreaterEq.ref.loc13: <function> = name_ref GreaterEq, file.%GreaterEq [template = file.%GreaterEq]
// CHECK:STDOUT: %.loc13_26: i32 = int_literal 0 [template = constants.%.8]
// CHECK:STDOUT: %Negate.ref.loc13: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc13_36: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc13_35.1: init i32 = call %Negate.ref.loc13(%.loc13_36) [template = constants.%.9]
// CHECK:STDOUT: %.loc13_25.1: i32 = value_of_initializer %.loc13_35.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_35.2: i32 = converted %.loc13_35.1, %.loc13_25.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_25.2: init bool = call %GreaterEq.ref.loc13(%.loc13_26, %.loc13_35.2) [template = constants.%.7]
// CHECK:STDOUT: %.loc13_13.1: bool = value_of_initializer %.loc13_25.2 [template = constants.%.7]
// CHECK:STDOUT: %.loc13_25.3: bool = converted %.loc13_25.2, %.loc13_13.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc13_25.3 br !if.expr.then.loc13 else br !if.expr.else.loc13
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc13:
// CHECK:STDOUT: %True.ref.loc13: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc13(%True.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc13:
// CHECK:STDOUT: %False.ref.loc13: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc13(%False.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc13:
// CHECK:STDOUT: %.loc13_13.2: type = block_arg !if.expr.result.loc13 [template = constants.%True]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %GreaterEq.ref: <function> = name_ref GreaterEq, file.%GreaterEq [template = file.%GreaterEq]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc17_19.1: init bool = call %GreaterEq.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc17_25: bool = value_of_initializer %.loc17_19.1
// CHECK:STDOUT: %.loc17_19.2: bool = converted %.loc17_19.1, %.loc17_25
// CHECK:STDOUT: return %.loc17_19.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+215
View File
@@ -0,0 +1,215 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_left_shift.carbon
fn LeftShift(a: i32, b: i32) -> i32 = "int.left_shift";
var arr: [i32; LeftShift(5, 2)];
let arr_p: [i32; 20]* = &arr;
fn RuntimeCall(a: i32, b: i32) -> i32 {
return LeftShift(a, b);
}
// TODO: Test mixed types for LHS and RHS.
// --- fail_bad_shift.carbon
package BadShift api;
fn LeftShift(a: i32, b: i32) -> i32 = "int.left_shift";
fn Negate(a: i32) -> i32 = "int.negate";
// Shift greater than size is disallowed.
let size_1: i32 = LeftShift(1, 31);
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: ERROR: Shift distance not in range [0, 32) in 1 << 32.
// CHECK:STDERR: let size_2: i32 = LeftShift(1, 32);
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR:
let size_2: i32 = LeftShift(1, 32);
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: ERROR: Shift distance not in range [0, 32) in 1 << 33.
// CHECK:STDERR: let size_3: i32 = LeftShift(1, 33);
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR:
let size_3: i32 = LeftShift(1, 33);
// Overflow is allowed if the shift distance is in bounds.
let overflow_1: i32 = LeftShift(1000, 31);
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:23: ERROR: Shift distance not in range [0, 32) in 1000 << 32.
// CHECK:STDERR: let overflow_2: i32 = LeftShift(1000, 32);
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR:
let overflow_2: i32 = LeftShift(1000, 32);
// Oversize shifts aren't allowed even if there's no overflow.
let no_overflow_1: i32 = LeftShift(0, 31);
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:26: ERROR: Shift distance not in range [0, 32) in 0 << 32.
// CHECK:STDERR: let no_overflow_2: i32 = LeftShift(0, 32);
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR:
let no_overflow_2: i32 = LeftShift(0, 32);
// Negative shifts aren't allowed either.
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+3]]:21: ERROR: Shift distance not in range [0, 32) in 1 << -1.
// CHECK:STDERR: let negative: i32 = LeftShift(1, Negate(1));
// CHECK:STDERR: ^~~~~~~~~~
let negative: i32 = LeftShift(1, Negate(1));
// CHECK:STDOUT: --- int_left_shift.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 5 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 20 [template]
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
// CHECK:STDOUT: %.5: type = ptr_type [i32; 20] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .LeftShift = %LeftShift
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %LeftShift: <function> = fn_decl @LeftShift [template] {
// CHECK:STDOUT: %a.loc2_14.1: i32 = param a
// CHECK:STDOUT: @LeftShift.%a: i32 = bind_name a, %a.loc2_14.1
// CHECK:STDOUT: %b.loc2_22.1: i32 = param b
// CHECK:STDOUT: @LeftShift.%b: i32 = bind_name b, %b.loc2_22.1
// CHECK:STDOUT: %return.var.loc2: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %LeftShift.ref: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc4_26: i32 = int_literal 5 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_29: i32 = int_literal 2 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_25: init i32 = call %LeftShift.ref(%.loc4_26, %.loc4_29) [template = constants.%.3]
// CHECK:STDOUT: %.loc4_31: type = array_type %.loc4_25, i32 [template = constants.%.4]
// CHECK:STDOUT: %arr.var: ref [i32; 20] = var arr
// CHECK:STDOUT: %arr: ref [i32; 20] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 20 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_20: type = array_type %.loc5_18, i32 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_21: type = ptr_type [i32; 20] [template = constants.%.5]
// CHECK:STDOUT: %arr.ref: ref [i32; 20] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_25: [i32; 20]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 20]* = bind_name arr_p, %.loc5_25
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @LeftShift(%a: i32, %b: i32) -> i32 = "int.left_shift";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %LeftShift.ref: <function> = name_ref LeftShift, file.%LeftShift [template = file.%LeftShift]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc8_19.1: init i32 = call %LeftShift.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_25: i32 = value_of_initializer %.loc8_19.1
// CHECK:STDOUT: %.loc8_19.2: i32 = converted %.loc8_19.1, %.loc8_25
// CHECK:STDOUT: return %.loc8_19.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_bad_shift.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 31 [template]
// CHECK:STDOUT: %.3: i32 = int_literal -2147483648 [template]
// CHECK:STDOUT: %.4: i32 = int_literal 32 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 33 [template]
// CHECK:STDOUT: %.6: i32 = int_literal 1000 [template]
// CHECK:STDOUT: %.7: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.8: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .LeftShift = %LeftShift
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: }
// CHECK:STDOUT: %LeftShift: <function> = fn_decl @LeftShift [template] {
// CHECK:STDOUT: %a.loc4_14.1: i32 = param a
// CHECK:STDOUT: @LeftShift.%a: i32 = bind_name a, %a.loc4_14.1
// CHECK:STDOUT: %b.loc4_22.1: i32 = param b
// CHECK:STDOUT: @LeftShift.%b: i32 = bind_name b, %b.loc4_22.1
// CHECK:STDOUT: %return.var.loc4: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc5_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc5_11.1
// CHECK:STDOUT: %return.var.loc5: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %LeftShift.ref.loc8: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc8_29: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc8_32: i32 = int_literal 31 [template = constants.%.2]
// CHECK:STDOUT: %.loc8_28.1: init i32 = call %LeftShift.ref.loc8(%.loc8_29, %.loc8_32) [template = constants.%.3]
// CHECK:STDOUT: %.loc8_35: i32 = value_of_initializer %.loc8_28.1 [template = constants.%.3]
// CHECK:STDOUT: %.loc8_28.2: i32 = converted %.loc8_28.1, %.loc8_35 [template = constants.%.3]
// CHECK:STDOUT: %size_1: i32 = bind_name size_1, %.loc8_28.2
// CHECK:STDOUT: %LeftShift.ref.loc13: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc13_29: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc13_32: i32 = int_literal 32 [template = constants.%.4]
// CHECK:STDOUT: %.loc13_28.1: init i32 = call %LeftShift.ref.loc13(%.loc13_29, %.loc13_32) [template = <error>]
// CHECK:STDOUT: %.loc13_35: i32 = value_of_initializer %.loc13_28.1 [template = <error>]
// CHECK:STDOUT: %.loc13_28.2: i32 = converted %.loc13_28.1, %.loc13_35 [template = <error>]
// CHECK:STDOUT: %size_2: i32 = bind_name size_2, %.loc13_28.2
// CHECK:STDOUT: %LeftShift.ref.loc18: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc18_29: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc18_32: i32 = int_literal 33 [template = constants.%.5]
// CHECK:STDOUT: %.loc18_28.1: init i32 = call %LeftShift.ref.loc18(%.loc18_29, %.loc18_32) [template = <error>]
// CHECK:STDOUT: %.loc18_35: i32 = value_of_initializer %.loc18_28.1 [template = <error>]
// CHECK:STDOUT: %.loc18_28.2: i32 = converted %.loc18_28.1, %.loc18_35 [template = <error>]
// CHECK:STDOUT: %size_3: i32 = bind_name size_3, %.loc18_28.2
// CHECK:STDOUT: %LeftShift.ref.loc21: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc21_33: i32 = int_literal 1000 [template = constants.%.6]
// CHECK:STDOUT: %.loc21_39: i32 = int_literal 31 [template = constants.%.2]
// CHECK:STDOUT: %.loc21_32.1: init i32 = call %LeftShift.ref.loc21(%.loc21_33, %.loc21_39) [template = constants.%.7]
// CHECK:STDOUT: %.loc21_42: i32 = value_of_initializer %.loc21_32.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc21_32.2: i32 = converted %.loc21_32.1, %.loc21_42 [template = constants.%.7]
// CHECK:STDOUT: %overflow_1: i32 = bind_name overflow_1, %.loc21_32.2
// CHECK:STDOUT: %LeftShift.ref.loc26: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc26_33: i32 = int_literal 1000 [template = constants.%.6]
// CHECK:STDOUT: %.loc26_39: i32 = int_literal 32 [template = constants.%.4]
// CHECK:STDOUT: %.loc26_32.1: init i32 = call %LeftShift.ref.loc26(%.loc26_33, %.loc26_39) [template = <error>]
// CHECK:STDOUT: %.loc26_42: i32 = value_of_initializer %.loc26_32.1 [template = <error>]
// CHECK:STDOUT: %.loc26_32.2: i32 = converted %.loc26_32.1, %.loc26_42 [template = <error>]
// CHECK:STDOUT: %overflow_2: i32 = bind_name overflow_2, %.loc26_32.2
// CHECK:STDOUT: %LeftShift.ref.loc29: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc29_36: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %.loc29_39: i32 = int_literal 31 [template = constants.%.2]
// CHECK:STDOUT: %.loc29_35.1: init i32 = call %LeftShift.ref.loc29(%.loc29_36, %.loc29_39) [template = constants.%.7]
// CHECK:STDOUT: %.loc29_42: i32 = value_of_initializer %.loc29_35.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc29_35.2: i32 = converted %.loc29_35.1, %.loc29_42 [template = constants.%.7]
// CHECK:STDOUT: %no_overflow_1: i32 = bind_name no_overflow_1, %.loc29_35.2
// CHECK:STDOUT: %LeftShift.ref.loc34: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc34_36: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %.loc34_39: i32 = int_literal 32 [template = constants.%.4]
// CHECK:STDOUT: %.loc34_35.1: init i32 = call %LeftShift.ref.loc34(%.loc34_36, %.loc34_39) [template = <error>]
// CHECK:STDOUT: %.loc34_42: i32 = value_of_initializer %.loc34_35.1 [template = <error>]
// CHECK:STDOUT: %.loc34_35.2: i32 = converted %.loc34_35.1, %.loc34_42 [template = <error>]
// CHECK:STDOUT: %no_overflow_2: i32 = bind_name no_overflow_2, %.loc34_35.2
// CHECK:STDOUT: %LeftShift.ref.loc40: <function> = name_ref LeftShift, %LeftShift [template = %LeftShift]
// CHECK:STDOUT: %.loc40_31: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %Negate.ref: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %.loc40_41: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc40_40.1: init i32 = call %Negate.ref(%.loc40_41) [template = constants.%.8]
// CHECK:STDOUT: %.loc40_30.1: i32 = value_of_initializer %.loc40_40.1 [template = constants.%.8]
// CHECK:STDOUT: %.loc40_40.2: i32 = converted %.loc40_40.1, %.loc40_30.1 [template = constants.%.8]
// CHECK:STDOUT: %.loc40_30.2: init i32 = call %LeftShift.ref.loc40(%.loc40_31, %.loc40_40.2) [template = <error>]
// CHECK:STDOUT: %.loc40_44: i32 = value_of_initializer %.loc40_30.2 [template = <error>]
// CHECK:STDOUT: %.loc40_30.3: i32 = converted %.loc40_30.2, %.loc40_44 [template = <error>]
// CHECK:STDOUT: %negative: i32 = bind_name negative, %.loc40_30.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @LeftShift(%a: i32, %b: i32) -> i32 = "int.left_shift";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
+215
View File
@@ -0,0 +1,215 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_less.carbon
fn Less(a: i32, b: i32) -> bool = "int.less";
fn Negate(a: i32) -> i32 = "int.negate";
class True {}
class False {}
fn F(true_: True, false_: False) {
true_ as (if Less(1, 2) then True else False);
false_ as (if Less(1, 1) then True else False);
false_ as (if Less(1, 0) then True else False);
true_ as (if Less(Negate(1), 0) then True else False);
false_ as (if Less(0, Negate(1)) then True else False);
}
fn RuntimeCall(a: i32, b: i32) -> bool {
return Less(a, b);
}
// CHECK:STDOUT: --- int_less.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %True: type = class_type @True [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %False: type = class_type @False [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.6: bool = bool_literal true [template]
// CHECK:STDOUT: %.7: bool = bool_literal false [template]
// CHECK:STDOUT: %.8: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.9: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Less = %Less
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: .True = %True.decl
// CHECK:STDOUT: .False = %False.decl
// CHECK:STDOUT: .F = %F
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Less: <function> = fn_decl @Less [template] {
// CHECK:STDOUT: %a.loc2_9.1: i32 = param a
// CHECK:STDOUT: @Less.%a: i32 = bind_name a, %a.loc2_9.1
// CHECK:STDOUT: %b.loc2_17.1: i32 = param b
// CHECK:STDOUT: @Less.%b: i32 = bind_name b, %b.loc2_17.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc3_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc3_11.1
// CHECK:STDOUT: %return.var.loc3: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %True.decl: type = class_decl @True [template = constants.%True] {}
// CHECK:STDOUT: %False.decl: type = class_decl @False [template = constants.%False] {}
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
// CHECK:STDOUT: %True.ref: type = name_ref True, %True.decl [template = constants.%True]
// CHECK:STDOUT: %true_.loc8_6.1: True = param true_
// CHECK:STDOUT: @F.%true_: True = bind_name true_, %true_.loc8_6.1
// CHECK:STDOUT: %False.ref: type = name_ref False, %False.decl [template = constants.%False]
// CHECK:STDOUT: %false_.loc8_19.1: False = param false_
// CHECK:STDOUT: @F.%false_: False = bind_name false_, %false_.loc8_19.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc16_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc16_16.1
// CHECK:STDOUT: %b.loc16_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc16_24.1
// CHECK:STDOUT: %return.var.loc16: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @True {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%True
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @False {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%False
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Less(%a: i32, %b: i32) -> bool = "int.less";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%true_: True, %false_: False) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %true_.ref.loc9: True = name_ref true_, %true_
// CHECK:STDOUT: %Less.ref.loc9: <function> = name_ref Less, file.%Less [template = file.%Less]
// CHECK:STDOUT: %.loc9_21: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc9_24: i32 = int_literal 2 [template = constants.%.5]
// CHECK:STDOUT: %.loc9_20.1: init bool = call %Less.ref.loc9(%.loc9_21, %.loc9_24) [template = constants.%.6]
// CHECK:STDOUT: %.loc9_13.1: bool = value_of_initializer %.loc9_20.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc9_20.2: bool = converted %.loc9_20.1, %.loc9_13.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc9_20.2 br !if.expr.then.loc9 else br !if.expr.else.loc9
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc9:
// CHECK:STDOUT: %True.ref.loc9: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc9(%True.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc9:
// CHECK:STDOUT: %False.ref.loc9: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc9(%False.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc9:
// CHECK:STDOUT: %.loc9_13.2: type = block_arg !if.expr.result.loc9 [template = constants.%True]
// CHECK:STDOUT: %false_.ref.loc10: False = name_ref false_, %false_
// CHECK:STDOUT: %Less.ref.loc10: <function> = name_ref Less, file.%Less [template = file.%Less]
// CHECK:STDOUT: %.loc10_22: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_25: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_21.1: init bool = call %Less.ref.loc10(%.loc10_22, %.loc10_25) [template = constants.%.7]
// CHECK:STDOUT: %.loc10_14.1: bool = value_of_initializer %.loc10_21.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc10_21.2: bool = converted %.loc10_21.1, %.loc10_14.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc10_21.2 br !if.expr.then.loc10 else br !if.expr.else.loc10
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc10:
// CHECK:STDOUT: %True.ref.loc10: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc10(%True.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc10:
// CHECK:STDOUT: %False.ref.loc10: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc10(%False.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc10:
// CHECK:STDOUT: %.loc10_14.2: type = block_arg !if.expr.result.loc10 [template = constants.%False]
// CHECK:STDOUT: %false_.ref.loc11: False = name_ref false_, %false_
// CHECK:STDOUT: %Less.ref.loc11: <function> = name_ref Less, file.%Less [template = file.%Less]
// CHECK:STDOUT: %.loc11_22: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc11_25: i32 = int_literal 0 [template = constants.%.8]
// CHECK:STDOUT: %.loc11_21.1: init bool = call %Less.ref.loc11(%.loc11_22, %.loc11_25) [template = constants.%.7]
// CHECK:STDOUT: %.loc11_14.1: bool = value_of_initializer %.loc11_21.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc11_21.2: bool = converted %.loc11_21.1, %.loc11_14.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc11_21.2 br !if.expr.then.loc11 else br !if.expr.else.loc11
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc11:
// CHECK:STDOUT: %True.ref.loc11: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc11(%True.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc11:
// CHECK:STDOUT: %False.ref.loc11: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc11(%False.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc11:
// CHECK:STDOUT: %.loc11_14.2: type = block_arg !if.expr.result.loc11 [template = constants.%False]
// CHECK:STDOUT: %true_.ref.loc12: True = name_ref true_, %true_
// CHECK:STDOUT: %Less.ref.loc12: <function> = name_ref Less, file.%Less [template = file.%Less]
// CHECK:STDOUT: %Negate.ref.loc12: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc12_28: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc12_27.1: init i32 = call %Negate.ref.loc12(%.loc12_28) [template = constants.%.9]
// CHECK:STDOUT: %.loc12_32: i32 = int_literal 0 [template = constants.%.8]
// CHECK:STDOUT: %.loc12_20.1: i32 = value_of_initializer %.loc12_27.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_27.2: i32 = converted %.loc12_27.1, %.loc12_20.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_20.2: init bool = call %Less.ref.loc12(%.loc12_27.2, %.loc12_32) [template = constants.%.6]
// CHECK:STDOUT: %.loc12_13.1: bool = value_of_initializer %.loc12_20.2 [template = constants.%.6]
// CHECK:STDOUT: %.loc12_20.3: bool = converted %.loc12_20.2, %.loc12_13.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc12_20.3 br !if.expr.then.loc12 else br !if.expr.else.loc12
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc12:
// CHECK:STDOUT: %True.ref.loc12: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc12(%True.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc12:
// CHECK:STDOUT: %False.ref.loc12: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc12(%False.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc12:
// CHECK:STDOUT: %.loc12_13.2: type = block_arg !if.expr.result.loc12 [template = constants.%True]
// CHECK:STDOUT: %false_.ref.loc13: False = name_ref false_, %false_
// CHECK:STDOUT: %Less.ref.loc13: <function> = name_ref Less, file.%Less [template = file.%Less]
// CHECK:STDOUT: %.loc13_22: i32 = int_literal 0 [template = constants.%.8]
// CHECK:STDOUT: %Negate.ref.loc13: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc13_32: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc13_31.1: init i32 = call %Negate.ref.loc13(%.loc13_32) [template = constants.%.9]
// CHECK:STDOUT: %.loc13_21.1: i32 = value_of_initializer %.loc13_31.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_31.2: i32 = converted %.loc13_31.1, %.loc13_21.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_21.2: init bool = call %Less.ref.loc13(%.loc13_22, %.loc13_31.2) [template = constants.%.7]
// CHECK:STDOUT: %.loc13_14.1: bool = value_of_initializer %.loc13_21.2 [template = constants.%.7]
// CHECK:STDOUT: %.loc13_21.3: bool = converted %.loc13_21.2, %.loc13_14.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc13_21.3 br !if.expr.then.loc13 else br !if.expr.else.loc13
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc13:
// CHECK:STDOUT: %True.ref.loc13: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc13(%True.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc13:
// CHECK:STDOUT: %False.ref.loc13: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc13(%False.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc13:
// CHECK:STDOUT: %.loc13_14.2: type = block_arg !if.expr.result.loc13 [template = constants.%False]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Less.ref: <function> = name_ref Less, file.%Less [template = file.%Less]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc17_14.1: init bool = call %Less.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc17_20: bool = value_of_initializer %.loc17_14.1
// CHECK:STDOUT: %.loc17_14.2: bool = converted %.loc17_14.1, %.loc17_20
// CHECK:STDOUT: return %.loc17_14.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+215
View File
@@ -0,0 +1,215 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_less_eq.carbon
fn LessEq(a: i32, b: i32) -> bool = "int.less_eq";
fn Negate(a: i32) -> i32 = "int.negate";
class True {}
class False {}
fn F(true_: True, false_: False) {
true_ as (if LessEq(1, 2) then True else False);
true_ as (if LessEq(1, 1) then True else False);
false_ as (if LessEq(1, 0) then True else False);
true_ as (if LessEq(Negate(1), 0) then True else False);
false_ as (if LessEq(0, Negate(1)) then True else False);
}
fn RuntimeCall(a: i32, b: i32) -> bool {
return LessEq(a, b);
}
// CHECK:STDOUT: --- int_less_eq.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %True: type = class_type @True [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %False: type = class_type @False [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.6: bool = bool_literal true [template]
// CHECK:STDOUT: %.7: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.8: bool = bool_literal false [template]
// CHECK:STDOUT: %.9: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .LessEq = %LessEq
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: .True = %True.decl
// CHECK:STDOUT: .False = %False.decl
// CHECK:STDOUT: .F = %F
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %LessEq: <function> = fn_decl @LessEq [template] {
// CHECK:STDOUT: %a.loc2_11.1: i32 = param a
// CHECK:STDOUT: @LessEq.%a: i32 = bind_name a, %a.loc2_11.1
// CHECK:STDOUT: %b.loc2_19.1: i32 = param b
// CHECK:STDOUT: @LessEq.%b: i32 = bind_name b, %b.loc2_19.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc3_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc3_11.1
// CHECK:STDOUT: %return.var.loc3: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %True.decl: type = class_decl @True [template = constants.%True] {}
// CHECK:STDOUT: %False.decl: type = class_decl @False [template = constants.%False] {}
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
// CHECK:STDOUT: %True.ref: type = name_ref True, %True.decl [template = constants.%True]
// CHECK:STDOUT: %true_.loc8_6.1: True = param true_
// CHECK:STDOUT: @F.%true_: True = bind_name true_, %true_.loc8_6.1
// CHECK:STDOUT: %False.ref: type = name_ref False, %False.decl [template = constants.%False]
// CHECK:STDOUT: %false_.loc8_19.1: False = param false_
// CHECK:STDOUT: @F.%false_: False = bind_name false_, %false_.loc8_19.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc16_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc16_16.1
// CHECK:STDOUT: %b.loc16_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc16_24.1
// CHECK:STDOUT: %return.var.loc16: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @True {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%True
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @False {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%False
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @LessEq(%a: i32, %b: i32) -> bool = "int.less_eq";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%true_: True, %false_: False) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %true_.ref.loc9: True = name_ref true_, %true_
// CHECK:STDOUT: %LessEq.ref.loc9: <function> = name_ref LessEq, file.%LessEq [template = file.%LessEq]
// CHECK:STDOUT: %.loc9_23: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc9_26: i32 = int_literal 2 [template = constants.%.5]
// CHECK:STDOUT: %.loc9_22.1: init bool = call %LessEq.ref.loc9(%.loc9_23, %.loc9_26) [template = constants.%.6]
// CHECK:STDOUT: %.loc9_13.1: bool = value_of_initializer %.loc9_22.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc9_22.2: bool = converted %.loc9_22.1, %.loc9_13.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc9_22.2 br !if.expr.then.loc9 else br !if.expr.else.loc9
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc9:
// CHECK:STDOUT: %True.ref.loc9: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc9(%True.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc9:
// CHECK:STDOUT: %False.ref.loc9: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc9(%False.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc9:
// CHECK:STDOUT: %.loc9_13.2: type = block_arg !if.expr.result.loc9 [template = constants.%True]
// CHECK:STDOUT: %true_.ref.loc10: True = name_ref true_, %true_
// CHECK:STDOUT: %LessEq.ref.loc10: <function> = name_ref LessEq, file.%LessEq [template = file.%LessEq]
// CHECK:STDOUT: %.loc10_23: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_26: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc10_22.1: init bool = call %LessEq.ref.loc10(%.loc10_23, %.loc10_26) [template = constants.%.6]
// CHECK:STDOUT: %.loc10_13.1: bool = value_of_initializer %.loc10_22.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc10_22.2: bool = converted %.loc10_22.1, %.loc10_13.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc10_22.2 br !if.expr.then.loc10 else br !if.expr.else.loc10
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc10:
// CHECK:STDOUT: %True.ref.loc10: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc10(%True.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc10:
// CHECK:STDOUT: %False.ref.loc10: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc10(%False.ref.loc10)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc10:
// CHECK:STDOUT: %.loc10_13.2: type = block_arg !if.expr.result.loc10 [template = constants.%True]
// CHECK:STDOUT: %false_.ref.loc11: False = name_ref false_, %false_
// CHECK:STDOUT: %LessEq.ref.loc11: <function> = name_ref LessEq, file.%LessEq [template = file.%LessEq]
// CHECK:STDOUT: %.loc11_24: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc11_27: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %.loc11_23.1: init bool = call %LessEq.ref.loc11(%.loc11_24, %.loc11_27) [template = constants.%.8]
// CHECK:STDOUT: %.loc11_14.1: bool = value_of_initializer %.loc11_23.1 [template = constants.%.8]
// CHECK:STDOUT: %.loc11_23.2: bool = converted %.loc11_23.1, %.loc11_14.1 [template = constants.%.8]
// CHECK:STDOUT: if %.loc11_23.2 br !if.expr.then.loc11 else br !if.expr.else.loc11
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc11:
// CHECK:STDOUT: %True.ref.loc11: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc11(%True.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc11:
// CHECK:STDOUT: %False.ref.loc11: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc11(%False.ref.loc11)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc11:
// CHECK:STDOUT: %.loc11_14.2: type = block_arg !if.expr.result.loc11 [template = constants.%False]
// CHECK:STDOUT: %true_.ref.loc12: True = name_ref true_, %true_
// CHECK:STDOUT: %LessEq.ref.loc12: <function> = name_ref LessEq, file.%LessEq [template = file.%LessEq]
// CHECK:STDOUT: %Negate.ref.loc12: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc12_30: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc12_29.1: init i32 = call %Negate.ref.loc12(%.loc12_30) [template = constants.%.9]
// CHECK:STDOUT: %.loc12_34: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %.loc12_22.1: i32 = value_of_initializer %.loc12_29.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_29.2: i32 = converted %.loc12_29.1, %.loc12_22.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc12_22.2: init bool = call %LessEq.ref.loc12(%.loc12_29.2, %.loc12_34) [template = constants.%.6]
// CHECK:STDOUT: %.loc12_13.1: bool = value_of_initializer %.loc12_22.2 [template = constants.%.6]
// CHECK:STDOUT: %.loc12_22.3: bool = converted %.loc12_22.2, %.loc12_13.1 [template = constants.%.6]
// CHECK:STDOUT: if %.loc12_22.3 br !if.expr.then.loc12 else br !if.expr.else.loc12
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc12:
// CHECK:STDOUT: %True.ref.loc12: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc12(%True.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc12:
// CHECK:STDOUT: %False.ref.loc12: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc12(%False.ref.loc12)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc12:
// CHECK:STDOUT: %.loc12_13.2: type = block_arg !if.expr.result.loc12 [template = constants.%True]
// CHECK:STDOUT: %false_.ref.loc13: False = name_ref false_, %false_
// CHECK:STDOUT: %LessEq.ref.loc13: <function> = name_ref LessEq, file.%LessEq [template = file.%LessEq]
// CHECK:STDOUT: %.loc13_24: i32 = int_literal 0 [template = constants.%.7]
// CHECK:STDOUT: %Negate.ref.loc13: <function> = name_ref Negate, file.%Negate [template = file.%Negate]
// CHECK:STDOUT: %.loc13_34: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc13_33.1: init i32 = call %Negate.ref.loc13(%.loc13_34) [template = constants.%.9]
// CHECK:STDOUT: %.loc13_23.1: i32 = value_of_initializer %.loc13_33.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_33.2: i32 = converted %.loc13_33.1, %.loc13_23.1 [template = constants.%.9]
// CHECK:STDOUT: %.loc13_23.2: init bool = call %LessEq.ref.loc13(%.loc13_24, %.loc13_33.2) [template = constants.%.8]
// CHECK:STDOUT: %.loc13_14.1: bool = value_of_initializer %.loc13_23.2 [template = constants.%.8]
// CHECK:STDOUT: %.loc13_23.3: bool = converted %.loc13_23.2, %.loc13_14.1 [template = constants.%.8]
// CHECK:STDOUT: if %.loc13_23.3 br !if.expr.then.loc13 else br !if.expr.else.loc13
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc13:
// CHECK:STDOUT: %True.ref.loc13: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc13(%True.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc13:
// CHECK:STDOUT: %False.ref.loc13: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc13(%False.ref.loc13)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc13:
// CHECK:STDOUT: %.loc13_14.2: type = block_arg !if.expr.result.loc13 [template = constants.%False]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %LessEq.ref: <function> = name_ref LessEq, file.%LessEq [template = file.%LessEq]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc17_16.1: init bool = call %LessEq.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc17_22: bool = value_of_initializer %.loc17_16.1
// CHECK:STDOUT: %.loc17_16.2: bool = converted %.loc17_16.1, %.loc17_22
// CHECK:STDOUT: return %.loc17_16.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -8,8 +8,8 @@
fn Negate(a: i32) -> i32 = "int.negate";
var arr: [i32; Negate(Negate(1))];
let arr_p: [i32; 1]* = &arr;
var arr: [i32; Negate(Negate(123))];
let arr_p: [i32; 123]* = &arr;
let n: i32 = Negate(1);
@@ -115,10 +115,12 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
// CHECK:STDOUT: --- int_negate.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.2: i32 = int_literal -1 [template]
// CHECK:STDOUT: %.1: i32 = int_literal 123 [template]
// CHECK:STDOUT: %.2: i32 = int_literal -123 [template]
// CHECK:STDOUT: %.3: type = array_type %.1, i32 [template]
// CHECK:STDOUT: %.4: type = ptr_type [i32; 1] [template]
// CHECK:STDOUT: %.4: type = ptr_type [i32; 123] [template]
// CHECK:STDOUT: %.5: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.6: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -134,25 +136,25 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate.ref.loc4_16: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %Negate.ref.loc4_23: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %.loc4_30: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_30: i32 = int_literal 123 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_29.1: init i32 = call %Negate.ref.loc4_23(%.loc4_30) [template = constants.%.2]
// CHECK:STDOUT: %.loc4_22.1: i32 = value_of_initializer %.loc4_29.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_29.2: i32 = converted %.loc4_29.1, %.loc4_22.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_22.2: init i32 = call %Negate.ref.loc4_16(%.loc4_29.2) [template = constants.%.1]
// CHECK:STDOUT: %.loc4_33: type = array_type %.loc4_22.2, i32 [template = constants.%.3]
// CHECK:STDOUT: %arr.var: ref [i32; 1] = var arr
// CHECK:STDOUT: %arr: ref [i32; 1] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_20: type = ptr_type [i32; 1] [template = constants.%.4]
// CHECK:STDOUT: %arr.ref: ref [i32; 1] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_24: [i32; 1]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 1]* = bind_name arr_p, %.loc5_24
// CHECK:STDOUT: %.loc4_35: type = array_type %.loc4_22.2, i32 [template = constants.%.3]
// CHECK:STDOUT: %arr.var: ref [i32; 123] = var arr
// CHECK:STDOUT: %arr: ref [i32; 123] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 123 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_21: type = array_type %.loc5_18, i32 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_22: type = ptr_type [i32; 123] [template = constants.%.4]
// CHECK:STDOUT: %arr.ref: ref [i32; 123] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_26: [i32; 123]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 123]* = bind_name arr_p, %.loc5_26
// CHECK:STDOUT: %Negate.ref.loc7: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %.loc7_21: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc7_20.1: init i32 = call %Negate.ref.loc7(%.loc7_21) [template = constants.%.2]
// CHECK:STDOUT: %.loc7_23: i32 = value_of_initializer %.loc7_20.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc7_20.2: i32 = converted %.loc7_20.1, %.loc7_23 [template = constants.%.2]
// CHECK:STDOUT: %.loc7_21: i32 = int_literal 1 [template = constants.%.5]
// CHECK:STDOUT: %.loc7_20.1: init i32 = call %Negate.ref.loc7(%.loc7_21) [template = constants.%.6]
// CHECK:STDOUT: %.loc7_23: i32 = value_of_initializer %.loc7_20.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc7_20.2: i32 = converted %.loc7_20.1, %.loc7_23 [template = constants.%.6]
// CHECK:STDOUT: %n: i32 = bind_name n, %.loc7_20.2
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc9_16.1: i32 = param a
+136
View File
@@ -0,0 +1,136 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_neq.carbon
fn Neq(a: i32, b: i32) -> bool = "int.neq";
class True {}
class False {}
fn F(true_: True, false_: False) {
false_ as (if Neq(1, 1) then True else False);
true_ as (if Neq(1, 2) then True else False);
}
fn RuntimeCall(a: i32, b: i32) -> bool {
return Neq(a, b);
}
// CHECK:STDOUT: --- int_neq.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %True: type = class_type @True [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %False: type = class_type @False [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.5: bool = bool_literal false [template]
// CHECK:STDOUT: %.6: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.7: bool = bool_literal true [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Neq = %Neq
// CHECK:STDOUT: .True = %True.decl
// CHECK:STDOUT: .False = %False.decl
// CHECK:STDOUT: .F = %F
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Neq: <function> = fn_decl @Neq [template] {
// CHECK:STDOUT: %a.loc2_8.1: i32 = param a
// CHECK:STDOUT: @Neq.%a: i32 = bind_name a, %a.loc2_8.1
// CHECK:STDOUT: %b.loc2_16.1: i32 = param b
// CHECK:STDOUT: @Neq.%b: i32 = bind_name b, %b.loc2_16.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %True.decl: type = class_decl @True [template = constants.%True] {}
// CHECK:STDOUT: %False.decl: type = class_decl @False [template = constants.%False] {}
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
// CHECK:STDOUT: %True.ref: type = name_ref True, %True.decl [template = constants.%True]
// CHECK:STDOUT: %true_.loc7_6.1: True = param true_
// CHECK:STDOUT: @F.%true_: True = bind_name true_, %true_.loc7_6.1
// CHECK:STDOUT: %False.ref: type = name_ref False, %False.decl [template = constants.%False]
// CHECK:STDOUT: %false_.loc7_19.1: False = param false_
// CHECK:STDOUT: @F.%false_: False = bind_name false_, %false_.loc7_19.1
// CHECK:STDOUT: }
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc12_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc12_16.1
// CHECK:STDOUT: %b.loc12_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc12_24.1
// CHECK:STDOUT: %return.var.loc12: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @True {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%True
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @False {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%False
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Neq(%a: i32, %b: i32) -> bool = "int.neq";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F(%true_: True, %false_: False) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %false_.ref: False = name_ref false_, %false_
// CHECK:STDOUT: %Neq.ref.loc8: <function> = name_ref Neq, file.%Neq [template = file.%Neq]
// CHECK:STDOUT: %.loc8_21: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc8_24: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc8_20.1: init bool = call %Neq.ref.loc8(%.loc8_21, %.loc8_24) [template = constants.%.5]
// CHECK:STDOUT: %.loc8_14.1: bool = value_of_initializer %.loc8_20.1 [template = constants.%.5]
// CHECK:STDOUT: %.loc8_20.2: bool = converted %.loc8_20.1, %.loc8_14.1 [template = constants.%.5]
// CHECK:STDOUT: if %.loc8_20.2 br !if.expr.then.loc8 else br !if.expr.else.loc8
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc8:
// CHECK:STDOUT: %True.ref.loc8: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc8(%True.ref.loc8)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc8:
// CHECK:STDOUT: %False.ref.loc8: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc8(%False.ref.loc8)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc8:
// CHECK:STDOUT: %.loc8_14.2: type = block_arg !if.expr.result.loc8 [template = constants.%False]
// CHECK:STDOUT: %true_.ref: True = name_ref true_, %true_
// CHECK:STDOUT: %Neq.ref.loc9: <function> = name_ref Neq, file.%Neq [template = file.%Neq]
// CHECK:STDOUT: %.loc9_20: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc9_23: i32 = int_literal 2 [template = constants.%.6]
// CHECK:STDOUT: %.loc9_19.1: init bool = call %Neq.ref.loc9(%.loc9_20, %.loc9_23) [template = constants.%.7]
// CHECK:STDOUT: %.loc9_13.1: bool = value_of_initializer %.loc9_19.1 [template = constants.%.7]
// CHECK:STDOUT: %.loc9_19.2: bool = converted %.loc9_19.1, %.loc9_13.1 [template = constants.%.7]
// CHECK:STDOUT: if %.loc9_19.2 br !if.expr.then.loc9 else br !if.expr.else.loc9
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.then.loc9:
// CHECK:STDOUT: %True.ref.loc9: type = name_ref True, file.%True.decl [template = constants.%True]
// CHECK:STDOUT: br !if.expr.result.loc9(%True.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.else.loc9:
// CHECK:STDOUT: %False.ref.loc9: type = name_ref False, file.%False.decl [template = constants.%False]
// CHECK:STDOUT: br !if.expr.result.loc9(%False.ref.loc9)
// CHECK:STDOUT:
// CHECK:STDOUT: !if.expr.result.loc9:
// CHECK:STDOUT: %.loc9_13.2: type = block_arg !if.expr.result.loc9 [template = constants.%True]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Neq.ref: <function> = name_ref Neq, file.%Neq [template = file.%Neq]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc13_13.1: init bool = call %Neq.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc13_19: bool = value_of_initializer %.loc13_13.1
// CHECK:STDOUT: %.loc13_13.2: bool = converted %.loc13_13.1, %.loc13_19
// CHECK:STDOUT: return %.loc13_13.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+75
View File
@@ -0,0 +1,75 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_or.carbon
fn Or(a: i32, b: i32) -> i32 = "int.or";
var arr: [i32; Or(12, 10)];
let arr_p: [i32; 14]* = &arr;
fn RuntimeCall(a: i32, b: i32) -> i32 {
return Or(a, b);
}
// CHECK:STDOUT: --- int_or.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 12 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 10 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 14 [template]
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
// CHECK:STDOUT: %.5: type = ptr_type [i32; 14] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Or = %Or
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Or: <function> = fn_decl @Or [template] {
// CHECK:STDOUT: %a.loc2_7.1: i32 = param a
// CHECK:STDOUT: @Or.%a: i32 = bind_name a, %a.loc2_7.1
// CHECK:STDOUT: %b.loc2_15.1: i32 = param b
// CHECK:STDOUT: @Or.%b: i32 = bind_name b, %b.loc2_15.1
// CHECK:STDOUT: %return.var.loc2: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Or.ref: <function> = name_ref Or, %Or [template = %Or]
// CHECK:STDOUT: %.loc4_19: i32 = int_literal 12 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_23: i32 = int_literal 10 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_18: init i32 = call %Or.ref(%.loc4_19, %.loc4_23) [template = constants.%.3]
// CHECK:STDOUT: %.loc4_26: type = array_type %.loc4_18, i32 [template = constants.%.4]
// CHECK:STDOUT: %arr.var: ref [i32; 14] = var arr
// CHECK:STDOUT: %arr: ref [i32; 14] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 14 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_20: type = array_type %.loc5_18, i32 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_21: type = ptr_type [i32; 14] [template = constants.%.5]
// CHECK:STDOUT: %arr.ref: ref [i32; 14] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_25: [i32; 14]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 14]* = bind_name arr_p, %.loc5_25
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Or(%a: i32, %b: i32) -> i32 = "int.or";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Or.ref: <function> = name_ref Or, file.%Or [template = file.%Or]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc8_12.1: init i32 = call %Or.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_18: i32 = value_of_initializer %.loc8_12.1
// CHECK:STDOUT: %.loc8_12.2: i32 = converted %.loc8_12.1, %.loc8_18
// CHECK:STDOUT: return %.loc8_12.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
+269
View File
@@ -0,0 +1,269 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_right_shift.carbon
fn RightShift(a: i32, b: i32) -> i32 = "int.right_shift";
var arr: [i32; RightShift(22, 2)];
let arr_p: [i32; 5]* = &arr;
fn RuntimeCall(a: i32, b: i32) -> i32 {
return RightShift(a, b);
}
// TODO: Test mixed types for LHS and RHS.
// --- arith_shift.carbon
// TODO: Also test unsigned / logical right shift.
package ArithShift api;
fn RightShift(a: i32, b: i32) -> i32 = "int.right_shift";
fn Negate(a: i32) -> i32 = "int.negate";
// -1 >> 1 is -1.
var arr1: [i32; Negate(RightShift(Negate(1), 1))];
let arr1_p: [i32; 1]* = &arr1;
// -10 >> 2 is -3.
var arr2: [i32; Negate(RightShift(Negate(10), 2))];
let arr2_p: [i32; 3]* = &arr2;
// --- fail_bad_shift.carbon
package BadShift api;
fn RightShift(a: i32, b: i32) -> i32 = "int.right_shift";
fn Negate(a: i32) -> i32 = "int.negate";
// Shift greater than size is disallowed.
let size_1: i32 = RightShift(1, 31);
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: ERROR: Shift distance not in range [0, 32) in 1 >> 32.
// CHECK:STDERR: let size_2: i32 = RightShift(1, 32);
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
let size_2: i32 = RightShift(1, 32);
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: ERROR: Shift distance not in range [0, 32) in 1 >> 33.
// CHECK:STDERR: let size_3: i32 = RightShift(1, 33);
// CHECK:STDERR: ^~~~~~~~~~~
// CHECK:STDERR:
let size_3: i32 = RightShift(1, 33);
// Negative shifts aren't allowed either.
// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+3]]:21: ERROR: Shift distance not in range [0, 32) in 1 >> -1.
// CHECK:STDERR: let negative: i32 = RightShift(1, Negate(1));
// CHECK:STDERR: ^~~~~~~~~~~
let negative: i32 = RightShift(1, Negate(1));
// CHECK:STDOUT: --- int_right_shift.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 22 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 5 [template]
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
// CHECK:STDOUT: %.5: type = ptr_type [i32; 5] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .RightShift = %RightShift
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %RightShift: <function> = fn_decl @RightShift [template] {
// CHECK:STDOUT: %a.loc2_15.1: i32 = param a
// CHECK:STDOUT: @RightShift.%a: i32 = bind_name a, %a.loc2_15.1
// CHECK:STDOUT: %b.loc2_23.1: i32 = param b
// CHECK:STDOUT: @RightShift.%b: i32 = bind_name b, %b.loc2_23.1
// CHECK:STDOUT: %return.var.loc2: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %RightShift.ref: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %.loc4_27: i32 = int_literal 22 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_31: i32 = int_literal 2 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_26: init i32 = call %RightShift.ref(%.loc4_27, %.loc4_31) [template = constants.%.3]
// CHECK:STDOUT: %.loc4_33: type = array_type %.loc4_26, i32 [template = constants.%.4]
// CHECK:STDOUT: %arr.var: ref [i32; 5] = var arr
// CHECK:STDOUT: %arr: ref [i32; 5] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 5 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_20: type = ptr_type [i32; 5] [template = constants.%.5]
// CHECK:STDOUT: %arr.ref: ref [i32; 5] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_24: [i32; 5]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 5]* = bind_name arr_p, %.loc5_24
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RightShift(%a: i32, %b: i32) -> i32 = "int.right_shift";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %RightShift.ref: <function> = name_ref RightShift, file.%RightShift [template = file.%RightShift]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc8_20.1: init i32 = call %RightShift.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_26: i32 = value_of_initializer %.loc8_20.1
// CHECK:STDOUT: %.loc8_20.2: i32 = converted %.loc8_20.1, %.loc8_26
// CHECK:STDOUT: return %.loc8_20.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- arith_shift.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.2: i32 = int_literal -1 [template]
// CHECK:STDOUT: %.3: type = array_type %.1, i32 [template]
// CHECK:STDOUT: %.4: type = ptr_type [i32; 1] [template]
// CHECK:STDOUT: %.5: i32 = int_literal 10 [template]
// CHECK:STDOUT: %.6: i32 = int_literal -10 [template]
// CHECK:STDOUT: %.7: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.8: i32 = int_literal -3 [template]
// CHECK:STDOUT: %.9: i32 = int_literal 3 [template]
// CHECK:STDOUT: %.10: type = array_type %.9, i32 [template]
// CHECK:STDOUT: %.11: type = ptr_type [i32; 3] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .RightShift = %RightShift
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: .arr1 = %arr1
// CHECK:STDOUT: .arr2 = %arr2
// CHECK:STDOUT: }
// CHECK:STDOUT: %RightShift: <function> = fn_decl @RightShift [template] {
// CHECK:STDOUT: %a.loc6_15.1: i32 = param a
// CHECK:STDOUT: @RightShift.%a: i32 = bind_name a, %a.loc6_15.1
// CHECK:STDOUT: %b.loc6_23.1: i32 = param b
// CHECK:STDOUT: @RightShift.%b: i32 = bind_name b, %b.loc6_23.1
// CHECK:STDOUT: %return.var.loc6: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc7_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc7_11.1
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate.ref.loc10_17: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %RightShift.ref.loc10: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %Negate.ref.loc10_35: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %.loc10_42: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc10_41.1: init i32 = call %Negate.ref.loc10_35(%.loc10_42) [template = constants.%.2]
// CHECK:STDOUT: %.loc10_46: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc10_34.1: i32 = value_of_initializer %.loc10_41.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc10_41.2: i32 = converted %.loc10_41.1, %.loc10_34.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc10_34.2: init i32 = call %RightShift.ref.loc10(%.loc10_41.2, %.loc10_46) [template = constants.%.2]
// CHECK:STDOUT: %.loc10_23.1: i32 = value_of_initializer %.loc10_34.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc10_34.3: i32 = converted %.loc10_34.2, %.loc10_23.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc10_23.2: init i32 = call %Negate.ref.loc10_17(%.loc10_34.3) [template = constants.%.1]
// CHECK:STDOUT: %.loc10_49: type = array_type %.loc10_23.2, i32 [template = constants.%.3]
// CHECK:STDOUT: %arr1.var: ref [i32; 1] = var arr1
// CHECK:STDOUT: %arr1: ref [i32; 1] = bind_name arr1, %arr1.var
// CHECK:STDOUT: %.loc11_19: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc11_20: type = array_type %.loc11_19, i32 [template = constants.%.3]
// CHECK:STDOUT: %.loc11_21: type = ptr_type [i32; 1] [template = constants.%.4]
// CHECK:STDOUT: %arr1.ref: ref [i32; 1] = name_ref arr1, %arr1
// CHECK:STDOUT: %.loc11_25: [i32; 1]* = addr_of %arr1.ref
// CHECK:STDOUT: %arr1_p: [i32; 1]* = bind_name arr1_p, %.loc11_25
// CHECK:STDOUT: %Negate.ref.loc14_17: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %RightShift.ref.loc14: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %Negate.ref.loc14_35: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %.loc14_42: i32 = int_literal 10 [template = constants.%.5]
// CHECK:STDOUT: %.loc14_41.1: init i32 = call %Negate.ref.loc14_35(%.loc14_42) [template = constants.%.6]
// CHECK:STDOUT: %.loc14_47: i32 = int_literal 2 [template = constants.%.7]
// CHECK:STDOUT: %.loc14_34.1: i32 = value_of_initializer %.loc14_41.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc14_41.2: i32 = converted %.loc14_41.1, %.loc14_34.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc14_34.2: init i32 = call %RightShift.ref.loc14(%.loc14_41.2, %.loc14_47) [template = constants.%.8]
// CHECK:STDOUT: %.loc14_23.1: i32 = value_of_initializer %.loc14_34.2 [template = constants.%.8]
// CHECK:STDOUT: %.loc14_34.3: i32 = converted %.loc14_34.2, %.loc14_23.1 [template = constants.%.8]
// CHECK:STDOUT: %.loc14_23.2: init i32 = call %Negate.ref.loc14_17(%.loc14_34.3) [template = constants.%.9]
// CHECK:STDOUT: %.loc14_50: type = array_type %.loc14_23.2, i32 [template = constants.%.10]
// CHECK:STDOUT: %arr2.var: ref [i32; 3] = var arr2
// CHECK:STDOUT: %arr2: ref [i32; 3] = bind_name arr2, %arr2.var
// CHECK:STDOUT: %.loc15_19: i32 = int_literal 3 [template = constants.%.9]
// CHECK:STDOUT: %.loc15_20: type = array_type %.loc15_19, i32 [template = constants.%.10]
// CHECK:STDOUT: %.loc15_21: type = ptr_type [i32; 3] [template = constants.%.11]
// CHECK:STDOUT: %arr2.ref: ref [i32; 3] = name_ref arr2, %arr2
// CHECK:STDOUT: %.loc15_25: [i32; 3]* = addr_of %arr2.ref
// CHECK:STDOUT: %arr2_p: [i32; 3]* = bind_name arr2_p, %.loc15_25
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RightShift(%a: i32, %b: i32) -> i32 = "int.right_shift";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_bad_shift.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 31 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.4: i32 = int_literal 32 [template]
// CHECK:STDOUT: %.5: i32 = int_literal 33 [template]
// CHECK:STDOUT: %.6: i32 = int_literal -1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .RightShift = %RightShift
// CHECK:STDOUT: .Negate = %Negate
// CHECK:STDOUT: }
// CHECK:STDOUT: %RightShift: <function> = fn_decl @RightShift [template] {
// CHECK:STDOUT: %a.loc4_15.1: i32 = param a
// CHECK:STDOUT: @RightShift.%a: i32 = bind_name a, %a.loc4_15.1
// CHECK:STDOUT: %b.loc4_23.1: i32 = param b
// CHECK:STDOUT: @RightShift.%b: i32 = bind_name b, %b.loc4_23.1
// CHECK:STDOUT: %return.var.loc4: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
// CHECK:STDOUT: %a.loc5_11.1: i32 = param a
// CHECK:STDOUT: @Negate.%a: i32 = bind_name a, %a.loc5_11.1
// CHECK:STDOUT: %return.var.loc5: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %RightShift.ref.loc8: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %.loc8_30: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc8_33: i32 = int_literal 31 [template = constants.%.2]
// CHECK:STDOUT: %.loc8_29.1: init i32 = call %RightShift.ref.loc8(%.loc8_30, %.loc8_33) [template = constants.%.3]
// CHECK:STDOUT: %.loc8_36: i32 = value_of_initializer %.loc8_29.1 [template = constants.%.3]
// CHECK:STDOUT: %.loc8_29.2: i32 = converted %.loc8_29.1, %.loc8_36 [template = constants.%.3]
// CHECK:STDOUT: %size_1: i32 = bind_name size_1, %.loc8_29.2
// CHECK:STDOUT: %RightShift.ref.loc13: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %.loc13_30: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc13_33: i32 = int_literal 32 [template = constants.%.4]
// CHECK:STDOUT: %.loc13_29.1: init i32 = call %RightShift.ref.loc13(%.loc13_30, %.loc13_33) [template = <error>]
// CHECK:STDOUT: %.loc13_36: i32 = value_of_initializer %.loc13_29.1 [template = <error>]
// CHECK:STDOUT: %.loc13_29.2: i32 = converted %.loc13_29.1, %.loc13_36 [template = <error>]
// CHECK:STDOUT: %size_2: i32 = bind_name size_2, %.loc13_29.2
// CHECK:STDOUT: %RightShift.ref.loc18: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %.loc18_30: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc18_33: i32 = int_literal 33 [template = constants.%.5]
// CHECK:STDOUT: %.loc18_29.1: init i32 = call %RightShift.ref.loc18(%.loc18_30, %.loc18_33) [template = <error>]
// CHECK:STDOUT: %.loc18_36: i32 = value_of_initializer %.loc18_29.1 [template = <error>]
// CHECK:STDOUT: %.loc18_29.2: i32 = converted %.loc18_29.1, %.loc18_36 [template = <error>]
// CHECK:STDOUT: %size_3: i32 = bind_name size_3, %.loc18_29.2
// CHECK:STDOUT: %RightShift.ref.loc24: <function> = name_ref RightShift, %RightShift [template = %RightShift]
// CHECK:STDOUT: %.loc24_32: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %Negate.ref: <function> = name_ref Negate, %Negate [template = %Negate]
// CHECK:STDOUT: %.loc24_42: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc24_41.1: init i32 = call %Negate.ref(%.loc24_42) [template = constants.%.6]
// CHECK:STDOUT: %.loc24_31.1: i32 = value_of_initializer %.loc24_41.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc24_41.2: i32 = converted %.loc24_41.1, %.loc24_31.1 [template = constants.%.6]
// CHECK:STDOUT: %.loc24_31.2: init i32 = call %RightShift.ref.loc24(%.loc24_32, %.loc24_41.2) [template = <error>]
// CHECK:STDOUT: %.loc24_45: i32 = value_of_initializer %.loc24_31.2 [template = <error>]
// CHECK:STDOUT: %.loc24_31.3: i32 = converted %.loc24_31.2, %.loc24_45 [template = <error>]
// CHECK:STDOUT: %negative: i32 = bind_name negative, %.loc24_31.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RightShift(%a: i32, %b: i32) -> i32 = "int.right_shift";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Negate(%a: i32) -> i32 = "int.negate";
// CHECK:STDOUT:
+75
View File
@@ -0,0 +1,75 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_xor.carbon
fn Xor(a: i32, b: i32) -> i32 = "int.xor";
var arr: [i32; Xor(12, 10)];
let arr_p: [i32; 6]* = &arr;
fn RuntimeCall(a: i32, b: i32) -> i32 {
return Xor(a, b);
}
// CHECK:STDOUT: --- int_xor.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 12 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 10 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 6 [template]
// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template]
// CHECK:STDOUT: %.5: type = ptr_type [i32; 6] [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Xor = %Xor
// CHECK:STDOUT: .arr = %arr
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Xor: <function> = fn_decl @Xor [template] {
// CHECK:STDOUT: %a.loc2_8.1: i32 = param a
// CHECK:STDOUT: @Xor.%a: i32 = bind_name a, %a.loc2_8.1
// CHECK:STDOUT: %b.loc2_16.1: i32 = param b
// CHECK:STDOUT: @Xor.%b: i32 = bind_name b, %b.loc2_16.1
// CHECK:STDOUT: %return.var.loc2: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Xor.ref: <function> = name_ref Xor, %Xor [template = %Xor]
// CHECK:STDOUT: %.loc4_20: i32 = int_literal 12 [template = constants.%.1]
// CHECK:STDOUT: %.loc4_24: i32 = int_literal 10 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_19: init i32 = call %Xor.ref(%.loc4_20, %.loc4_24) [template = constants.%.3]
// CHECK:STDOUT: %.loc4_27: type = array_type %.loc4_19, i32 [template = constants.%.4]
// CHECK:STDOUT: %arr.var: ref [i32; 6] = var arr
// CHECK:STDOUT: %arr: ref [i32; 6] = bind_name arr, %arr.var
// CHECK:STDOUT: %.loc5_18: i32 = int_literal 6 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_20: type = ptr_type [i32; 6] [template = constants.%.5]
// CHECK:STDOUT: %arr.ref: ref [i32; 6] = name_ref arr, %arr
// CHECK:STDOUT: %.loc5_24: [i32; 6]* = addr_of %arr.ref
// CHECK:STDOUT: %arr_p: [i32; 6]* = bind_name arr_p, %.loc5_24
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Xor(%a: i32, %b: i32) -> i32 = "int.xor";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Xor.ref: <function> = name_ref Xor, file.%Xor [template = file.%Xor]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc8_13.1: init i32 = call %Xor.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc8_19: i32 = value_of_initializer %.loc8_13.1
// CHECK:STDOUT: %.loc8_13.2: i32 = converted %.loc8_13.1, %.loc8_19
// CHECK:STDOUT: return %.loc8_13.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
-101
View File
@@ -1,101 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_eq.carbon
fn Eq(a: i32, b: i32) -> bool = "int.eq";
// TODO: Use a test that will fail to compile if we get the wrong value.
let b_true: bool = Eq(1, 1);
let b_false: bool = Eq(1, 2);
fn RuntimeCall(a: i32, b: i32) -> bool {
return Eq(a, b);
}
// --- fail_bad_decl.carbon
package FailBadDecl api;
// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+3]]:1: ERROR: Invalid signature for builtin function "int.eq".
// CHECK:STDERR: fn WrongResult(a: i32, b: i32) -> i32 = "int.eq";
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fn WrongResult(a: i32, b: i32) -> i32 = "int.eq";
// CHECK:STDOUT: --- int_eq.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.2: bool = bool_literal true [template]
// CHECK:STDOUT: %.3: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.4: bool = bool_literal false [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Eq = %Eq
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Eq: <function> = fn_decl @Eq [template] {
// CHECK:STDOUT: %a.loc2_7.1: i32 = param a
// CHECK:STDOUT: @Eq.%a: i32 = bind_name a, %a.loc2_7.1
// CHECK:STDOUT: %b.loc2_15.1: i32 = param b
// CHECK:STDOUT: @Eq.%b: i32 = bind_name b, %b.loc2_15.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Eq.ref.loc5: <function> = name_ref Eq, %Eq [template = %Eq]
// CHECK:STDOUT: %.loc5_23: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_26: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_22.1: init bool = call %Eq.ref.loc5(%.loc5_23, %.loc5_26) [template = constants.%.2]
// CHECK:STDOUT: %.loc5_28: bool = value_of_initializer %.loc5_22.1 [template = constants.%.2]
// CHECK:STDOUT: %.loc5_22.2: bool = converted %.loc5_22.1, %.loc5_28 [template = constants.%.2]
// CHECK:STDOUT: %b_true: bool = bind_name b_true, %.loc5_22.2
// CHECK:STDOUT: %Eq.ref.loc6: <function> = name_ref Eq, %Eq [template = %Eq]
// CHECK:STDOUT: %.loc6_24: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc6_27: i32 = int_literal 2 [template = constants.%.3]
// CHECK:STDOUT: %.loc6_23.1: init bool = call %Eq.ref.loc6(%.loc6_24, %.loc6_27) [template = constants.%.4]
// CHECK:STDOUT: %.loc6_29: bool = value_of_initializer %.loc6_23.1 [template = constants.%.4]
// CHECK:STDOUT: %.loc6_23.2: bool = converted %.loc6_23.1, %.loc6_29 [template = constants.%.4]
// CHECK:STDOUT: %b_false: bool = bind_name b_false, %.loc6_23.2
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc8_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc8_16.1
// CHECK:STDOUT: %b.loc8_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc8_24.1
// CHECK:STDOUT: %return.var.loc8: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Eq(%a: i32, %b: i32) -> bool = "int.eq";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Eq.ref: <function> = name_ref Eq, file.%Eq [template = file.%Eq]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc9_12.1: init bool = call %Eq.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc9_18: bool = value_of_initializer %.loc9_12.1
// CHECK:STDOUT: %.loc9_12.2: bool = converted %.loc9_12.1, %.loc9_18
// CHECK:STDOUT: return %.loc9_12.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_bad_decl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .WrongResult = %WrongResult
// CHECK:STDOUT: }
// CHECK:STDOUT: %WrongResult: <function> = fn_decl @WrongResult [template] {
// CHECK:STDOUT: %a.loc7_16.1: i32 = param a
// CHECK:STDOUT: @WrongResult.%a: i32 = bind_name a, %a.loc7_16.1
// CHECK:STDOUT: %b.loc7_24.1: i32 = param b
// CHECK:STDOUT: @WrongResult.%b: i32 = bind_name b, %b.loc7_24.1
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @WrongResult(%a: i32, %b: i32) -> i32;
// CHECK:STDOUT:
-75
View File
@@ -1,75 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// --- int_neq.carbon
fn Neq(a: i32, b: i32) -> bool = "int.neq";
// TODO: Use a test that will fail to compile if we get the wrong value.
let b_true: bool = Neq(1, 2);
let b_false: bool = Neq(1, 1);
fn RuntimeCall(a: i32, b: i32) -> bool {
return Neq(a, b);
}
// CHECK:STDOUT: --- int_neq.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.2: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.3: bool = bool_literal true [template]
// CHECK:STDOUT: %.4: bool = bool_literal false [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Neq = %Neq
// CHECK:STDOUT: .RuntimeCall = %RuntimeCall
// CHECK:STDOUT: }
// CHECK:STDOUT: %Neq: <function> = fn_decl @Neq [template] {
// CHECK:STDOUT: %a.loc2_8.1: i32 = param a
// CHECK:STDOUT: @Neq.%a: i32 = bind_name a, %a.loc2_8.1
// CHECK:STDOUT: %b.loc2_16.1: i32 = param b
// CHECK:STDOUT: @Neq.%b: i32 = bind_name b, %b.loc2_16.1
// CHECK:STDOUT: %return.var.loc2: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Neq.ref.loc5: <function> = name_ref Neq, %Neq [template = %Neq]
// CHECK:STDOUT: %.loc5_24: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc5_27: i32 = int_literal 2 [template = constants.%.2]
// CHECK:STDOUT: %.loc5_23.1: init bool = call %Neq.ref.loc5(%.loc5_24, %.loc5_27) [template = constants.%.3]
// CHECK:STDOUT: %.loc5_29: bool = value_of_initializer %.loc5_23.1 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_23.2: bool = converted %.loc5_23.1, %.loc5_29 [template = constants.%.3]
// CHECK:STDOUT: %b_true: bool = bind_name b_true, %.loc5_23.2
// CHECK:STDOUT: %Neq.ref.loc6: <function> = name_ref Neq, %Neq [template = %Neq]
// CHECK:STDOUT: %.loc6_25: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc6_28: i32 = int_literal 1 [template = constants.%.1]
// CHECK:STDOUT: %.loc6_24.1: init bool = call %Neq.ref.loc6(%.loc6_25, %.loc6_28) [template = constants.%.4]
// CHECK:STDOUT: %.loc6_30: bool = value_of_initializer %.loc6_24.1 [template = constants.%.4]
// CHECK:STDOUT: %.loc6_24.2: bool = converted %.loc6_24.1, %.loc6_30 [template = constants.%.4]
// CHECK:STDOUT: %b_false: bool = bind_name b_false, %.loc6_24.2
// CHECK:STDOUT: %RuntimeCall: <function> = fn_decl @RuntimeCall [template] {
// CHECK:STDOUT: %a.loc8_16.1: i32 = param a
// CHECK:STDOUT: @RuntimeCall.%a: i32 = bind_name a, %a.loc8_16.1
// CHECK:STDOUT: %b.loc8_24.1: i32 = param b
// CHECK:STDOUT: @RuntimeCall.%b: i32 = bind_name b, %b.loc8_24.1
// CHECK:STDOUT: %return.var.loc8: ref bool = var <return slot>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Neq(%a: i32, %b: i32) -> bool = "int.neq";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @RuntimeCall(%a: i32, %b: i32) -> bool {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Neq.ref: <function> = name_ref Neq, file.%Neq [template = file.%Neq]
// CHECK:STDOUT: %a.ref: i32 = name_ref a, %a
// CHECK:STDOUT: %b.ref: i32 = name_ref b, %b
// CHECK:STDOUT: %.loc9_13.1: init bool = call %Neq.ref(%a.ref, %b.ref)
// CHECK:STDOUT: %.loc9_19: bool = value_of_initializer %.loc9_13.1
// CHECK:STDOUT: %.loc9_13.2: bool = converted %.loc9_13.1, %.loc9_19
// CHECK:STDOUT: return %.loc9_13.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -246,6 +246,7 @@ CARBON_DIAGNOSTIC_KIND(BreakOutsideLoop)
CARBON_DIAGNOSTIC_KIND(CompileTimeDivisionByZero)
CARBON_DIAGNOSTIC_KIND(CompileTimeIntegerOverflow)
CARBON_DIAGNOSTIC_KIND(CompileTimeIntegerNegateOverflow)
CARBON_DIAGNOSTIC_KIND(CompileTimeShiftOutOfRange)
CARBON_DIAGNOSTIC_KIND(ContinueOutsideLoop)
CARBON_DIAGNOSTIC_KIND(CopyOfUncopyableType)
CARBON_DIAGNOSTIC_KIND(DerefOfNonPointer)
+81 -7
View File
@@ -12,7 +12,6 @@
#include "llvm/Support/Casting.h"
#include "toolchain/lower/function_context.h"
#include "toolchain/sem_ir/builtin_function_kind.h"
#include "toolchain/sem_ir/function.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/typed_insts.h"
@@ -168,6 +167,36 @@ auto HandleBuiltin(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
CARBON_FATAL() << "TODO: Add support: " << inst;
}
// Get the predicate to use for an `icmp` instruction generated for the
// specified builtin.
static auto GetBuiltinICmpPredicate(SemIR::BuiltinFunctionKind builtin_kind,
bool is_signed)
-> llvm::CmpInst::Predicate {
switch (builtin_kind) {
case SemIR::BuiltinFunctionKind::IntEq:
return llvm::CmpInst::ICMP_EQ;
case SemIR::BuiltinFunctionKind::IntNeq:
return llvm::CmpInst::ICMP_NE;
case SemIR::BuiltinFunctionKind::IntLess:
return is_signed ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
case SemIR::BuiltinFunctionKind::IntLessEq:
return is_signed ? llvm::CmpInst::ICMP_SLE : llvm::CmpInst::ICMP_ULE;
case SemIR::BuiltinFunctionKind::IntGreater:
return is_signed ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
case SemIR::BuiltinFunctionKind::IntGreaterEq:
return is_signed ? llvm::CmpInst::ICMP_SGE : llvm::CmpInst::ICMP_UGE;
default:
CARBON_FATAL() << "Unexpected builtin kind " << builtin_kind;
}
}
// Returns whether the specified instruction has a signed integer type.
static auto IsSignedInt(FunctionContext& context, SemIR::InstId int_id)
-> bool {
return context.sem_ir().types().IsSignedInt(
context.sem_ir().insts().Get(int_id).type_id());
}
// Handles a call to a builtin function.
static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
SemIR::BuiltinFunctionKind builtin_kind,
@@ -191,6 +220,15 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
/*HasNSW=*/SignedOverflowIsUB));
return;
}
case SemIR::BuiltinFunctionKind::IntComplement: {
// Lower `^x` as `-1 ^ x`.
auto* operand = context.GetValue(arg_ids[0]);
context.SetLocal(inst_id,
context.builder().CreateXor(
llvm::ConstantInt::getSigned(operand->getType(), -1),
operand, "cmpl"));
return;
}
case SemIR::BuiltinFunctionKind::IntAdd: {
context.SetLocal(inst_id, context.builder().CreateAdd(
context.GetValue(arg_ids[0]),
@@ -227,16 +265,52 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
context.GetValue(arg_ids[1]), "rem"));
return;
}
case SemIR::BuiltinFunctionKind::IntEq: {
context.SetLocal(inst_id, context.builder().CreateICmpEQ(
case SemIR::BuiltinFunctionKind::IntAnd: {
context.SetLocal(inst_id, context.builder().CreateAnd(
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "eq"));
context.GetValue(arg_ids[1]), "and"));
return;
}
case SemIR::BuiltinFunctionKind::IntNeq: {
context.SetLocal(inst_id, context.builder().CreateICmpNE(
case SemIR::BuiltinFunctionKind::IntOr: {
context.SetLocal(inst_id, context.builder().CreateOr(
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "neq"));
context.GetValue(arg_ids[1]), "or"));
return;
}
case SemIR::BuiltinFunctionKind::IntXor: {
context.SetLocal(inst_id, context.builder().CreateXor(
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "xor"));
return;
}
case SemIR::BuiltinFunctionKind::IntLeftShift: {
context.SetLocal(inst_id, context.builder().CreateShl(
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "shl"));
return;
}
case SemIR::BuiltinFunctionKind::IntRightShift: {
context.SetLocal(inst_id, IsSignedInt(context, inst_id)
? context.builder().CreateAShr(
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "shr")
: context.builder().CreateLShr(
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "shr"));
return;
}
case SemIR::BuiltinFunctionKind::IntEq:
case SemIR::BuiltinFunctionKind::IntNeq:
case SemIR::BuiltinFunctionKind::IntLess:
case SemIR::BuiltinFunctionKind::IntLessEq:
case SemIR::BuiltinFunctionKind::IntGreater:
case SemIR::BuiltinFunctionKind::IntGreaterEq: {
context.SetLocal(inst_id,
context.builder().CreateICmp(
GetBuiltinICmpPredicate(
builtin_kind, IsSignedInt(context, arg_ids[0])),
context.GetValue(arg_ids[0]),
context.GetValue(arg_ids[1]), "cmp"));
return;
}
}
+136
View File
@@ -4,13 +4,149 @@
//
// AUTOUPDATE
fn Negate(a: i32) -> i32 = "int.negate";
fn TestNegate(a: i32) -> i32 { return Negate(a); }
fn Add(a: i32, b: i32) -> i32 = "int.add";
fn TestAdd(a: i32, b: i32) -> i32 { return Add(a, b); }
fn Sub(a: i32, b: i32) -> i32 = "int.sub";
fn TestSub(a: i32, b: i32) -> i32 { return Sub(a, b); }
fn Mul(a: i32, b: i32) -> i32 = "int.mul";
fn TestMul(a: i32, b: i32) -> i32 { return Mul(a, b); }
fn Div(a: i32, b: i32) -> i32 = "int.div";
fn TestDiv(a: i32, b: i32) -> i32 { return Div(a, b); }
fn Mod(a: i32, b: i32) -> i32 = "int.mod";
fn TestMod(a: i32, b: i32) -> i32 { return Mod(a, b); }
fn Complement(a: i32) -> i32 = "int.complement";
fn TestComplement(a: i32) -> i32 { return Complement(a); }
fn And(a: i32, b: i32) -> i32 = "int.and";
fn TestAnd(a: i32, b: i32) -> i32 { return And(a, b); }
fn Or(a: i32, b: i32) -> i32 = "int.or";
fn TestOr(a: i32, b: i32) -> i32 { return Or(a, b); }
fn Xor(a: i32, b: i32) -> i32 = "int.xor";
fn TestXor(a: i32, b: i32) -> i32 { return Xor(a, b); }
fn LeftShift(a: i32, b: i32) -> i32 = "int.left_shift";
fn TestLeftShift(a: i32, b: i32) -> i32 { return LeftShift(a, b); }
fn RightShift(a: i32, b: i32) -> i32 = "int.right_shift";
fn TestRightShift(a: i32, b: i32) -> i32 { return RightShift(a, b); }
fn Eq(a: i32, b: i32) -> bool = "int.eq";
fn TestEq(a: i32, b: i32) -> bool { return Eq(a, b); }
fn Neq(a: i32, b: i32) -> bool = "int.neq";
fn TestNeq(a: i32, b: i32) -> bool { return Neq(a, b); }
fn Less(a: i32, b: i32) -> bool = "int.less";
fn TestLess(a: i32, b: i32) -> bool { return Less(a, b); }
fn LessEq(a: i32, b: i32) -> bool = "int.less_eq";
fn TestLessEq(a: i32, b: i32) -> bool { return LessEq(a, b); }
fn Greater(a: i32, b: i32) -> bool = "int.greater";
fn TestGreater(a: i32, b: i32) -> bool { return Greater(a, b); }
fn GreaterEq(a: i32, b: i32) -> bool = "int.greater_eq";
fn TestGreaterEq(a: i32, b: i32) -> bool { return GreaterEq(a, b); }
// CHECK:STDOUT: ; ModuleID = 'int.carbon'
// CHECK:STDOUT: source_filename = "int.carbon"
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestNegate(i32 %a) {
// CHECK:STDOUT: %neg = sub i32 0, %a
// CHECK:STDOUT: ret i32 %neg
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestAdd(i32 %a, i32 %b) {
// CHECK:STDOUT: %add = add i32 %a, %b
// CHECK:STDOUT: ret i32 %add
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestSub(i32 %a, i32 %b) {
// CHECK:STDOUT: %sub = sub i32 %a, %b
// CHECK:STDOUT: ret i32 %sub
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestMul(i32 %a, i32 %b) {
// CHECK:STDOUT: %mul = mul i32 %a, %b
// CHECK:STDOUT: ret i32 %mul
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestDiv(i32 %a, i32 %b) {
// CHECK:STDOUT: %div = sdiv i32 %a, %b
// CHECK:STDOUT: ret i32 %div
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestMod(i32 %a, i32 %b) {
// CHECK:STDOUT: %rem = srem i32 %a, %b
// CHECK:STDOUT: ret i32 %rem
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestComplement(i32 %a) {
// CHECK:STDOUT: %cmpl = xor i32 -1, %a
// CHECK:STDOUT: ret i32 %cmpl
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestAnd(i32 %a, i32 %b) {
// CHECK:STDOUT: %and = and i32 %a, %b
// CHECK:STDOUT: ret i32 %and
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestOr(i32 %a, i32 %b) {
// CHECK:STDOUT: %or = or i32 %a, %b
// CHECK:STDOUT: ret i32 %or
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestXor(i32 %a, i32 %b) {
// CHECK:STDOUT: %xor = xor i32 %a, %b
// CHECK:STDOUT: ret i32 %xor
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestLeftShift(i32 %a, i32 %b) {
// CHECK:STDOUT: %shl = shl i32 %a, %b
// CHECK:STDOUT: ret i32 %shl
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @TestRightShift(i32 %a, i32 %b) {
// CHECK:STDOUT: %shr = ashr i32 %a, %b
// CHECK:STDOUT: ret i32 %shr
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i1 @TestEq(i32 %a, i32 %b) {
// CHECK:STDOUT: %cmp = icmp eq i32 %a, %b
// CHECK:STDOUT: ret i1 %cmp
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i1 @TestNeq(i32 %a, i32 %b) {
// CHECK:STDOUT: %cmp = icmp ne i32 %a, %b
// CHECK:STDOUT: ret i1 %cmp
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i1 @TestLess(i32 %a, i32 %b) {
// CHECK:STDOUT: %cmp = icmp slt i32 %a, %b
// CHECK:STDOUT: ret i1 %cmp
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i1 @TestLessEq(i32 %a, i32 %b) {
// CHECK:STDOUT: %cmp = icmp sle i32 %a, %b
// CHECK:STDOUT: ret i1 %cmp
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i1 @TestGreater(i32 %a, i32 %b) {
// CHECK:STDOUT: %cmp = icmp sgt i32 %a, %b
// CHECK:STDOUT: ret i1 %cmp
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i1 @TestGreaterEq(i32 %a, i32 %b) {
// CHECK:STDOUT: %cmp = icmp sge i32 %a, %b
// CHECK:STDOUT: ret i1 %cmp
// CHECK:STDOUT: }
+46 -2
View File
@@ -24,14 +24,14 @@ struct BuiltinInfo {
};
// The maximum number of type parameters any builtin needs.
constexpr int MaxTypeParams = 1;
constexpr int MaxTypeParams = 2;
// State used when validating a builtin signature that persists between
// individual checks.
struct ValidateState {
// The type values of type parameters in the builtin signature. Invalid if
// either no value has been deduced yet or the parameter is not used.
TypeId type_params[MaxTypeParams] = {TypeId::Invalid};
TypeId type_params[MaxTypeParams] = {TypeId::Invalid, TypeId::Invalid};
};
// Constraint that a type is generic type parameter `I` of the builtin,
@@ -125,6 +125,10 @@ namespace BuiltinFunctionInfo {
// generic type parameter that is constrained to be an integer type.
using IntT = TypeParam<0, AnyInt>;
// Convenience name used in the builtin type signatures below for a second
// generic type parameter that is constrained to be an integer type.
using IntU = TypeParam<1, AnyInt>;
// Not a builtin function.
constexpr BuiltinInfo None = {"", nullptr};
@@ -152,6 +156,30 @@ constexpr BuiltinInfo IntDiv = {"int.div",
constexpr BuiltinInfo IntMod = {"int.mod",
ValidateSignature<auto(IntT, IntT)->IntT>};
// "int.complement": integer bitwise complement.
constexpr BuiltinInfo IntComplement = {"int.complement",
ValidateSignature<auto(IntT)->IntT>};
// "int.and": integer bitwise and.
constexpr BuiltinInfo IntAnd = {"int.and",
ValidateSignature<auto(IntT, IntT)->IntT>};
// "int.or": integer bitwise or.
constexpr BuiltinInfo IntOr = {"int.or",
ValidateSignature<auto(IntT, IntT)->IntT>};
// "int.xor": integer bitwise xor.
constexpr BuiltinInfo IntXor = {"int.xor",
ValidateSignature<auto(IntT, IntT)->IntT>};
// "int.left_shift": integer left shift.
constexpr BuiltinInfo IntLeftShift = {
"int.left_shift", ValidateSignature<auto(IntT, IntU)->IntT>};
// "int.left_shift": integer right shift.
constexpr BuiltinInfo IntRightShift = {
"int.right_shift", ValidateSignature<auto(IntT, IntU)->IntT>};
// "int.eq": integer equality comparison.
constexpr BuiltinInfo IntEq = {"int.eq",
ValidateSignature<auto(IntT, IntT)->Bool>};
@@ -160,6 +188,22 @@ constexpr BuiltinInfo IntEq = {"int.eq",
constexpr BuiltinInfo IntNeq = {"int.neq",
ValidateSignature<auto(IntT, IntT)->Bool>};
// "int.less": integer less than comparison.
constexpr BuiltinInfo IntLess = {"int.less",
ValidateSignature<auto(IntT, IntT)->Bool>};
// "int.less_eq": integer less than or equal comparison.
constexpr BuiltinInfo IntLessEq = {"int.less_eq",
ValidateSignature<auto(IntT, IntT)->Bool>};
// "int.greater": integer greater than comparison.
constexpr BuiltinInfo IntGreater = {"int.greater",
ValidateSignature<auto(IntT, IntT)->Bool>};
// "int.greater_eq": integer greater than or equal comparison.
constexpr BuiltinInfo IntGreaterEq = {
"int.greater_eq", ValidateSignature<auto(IntT, IntT)->Bool>};
} // namespace BuiltinFunctionInfo
CARBON_DEFINE_ENUM_CLASS_NAMES(BuiltinFunctionKind) = {
@@ -17,13 +17,29 @@
#endif
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(None)
// Integer arithmetic.
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntNegate)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntAdd)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntSub)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntMul)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntDiv)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntMod)
// Integer bitwise.
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntComplement)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntAnd)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntOr)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntXor)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntLeftShift)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntRightShift)
// Integer comparison.
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntEq)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntNeq)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntLess)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntLessEq)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntGreater)
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntGreaterEq)
#undef CARBON_SEM_IR_BUILTIN_FUNCTION_KIND