mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 09:31:04 +01:00
Add builtins for integer bitwise, bit-shift, and relational comparison operators. (#3853)
This commit is contained in:
@@ -7,6 +7,7 @@ circularly
|
||||
compiletime
|
||||
copyable
|
||||
crate
|
||||
createor
|
||||
crossreference
|
||||
falsy
|
||||
forin
|
||||
|
||||
+112
-30
@@ -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;
|
||||
|
||||
Vendored
@@ -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:
|
||||
@@ -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:
|
||||
Vendored
+162
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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
@@ -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:
|
||||
@@ -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:
|
||||
Vendored
Vendored
+21
-19
@@ -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
@@ -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
@@ -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:
|
||||
@@ -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:
|
||||
Vendored
@@ -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
@@ -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:
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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: }
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user