mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:00:13 +01:00
Add solutions for advent of code 2024 day 1 to examples/. (#4673)
In order to support these examples, this adds two new builtins to the toolchain: `print.char` and `read.char`, which map to the libc functions `putchar` and `getchar`.
This commit is contained in:
+2
-1
@@ -5,9 +5,10 @@
|
||||
load("//bazel/manifest:defs.bzl", "manifest")
|
||||
|
||||
# Raw prelude files.
|
||||
# TODO: This includes all of Core, not just the prelude.
|
||||
filegroup(
|
||||
name = "prelude_files",
|
||||
srcs = ["prelude.carbon"] + glob(["prelude/**/*.carbon"]),
|
||||
srcs = glob(["**/*.carbon"]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// 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
|
||||
|
||||
package Core library "io";
|
||||
|
||||
import library "prelude";
|
||||
|
||||
// TODO: Support printing other types.
|
||||
// TODO: Consider rewriting using native support once library support exists.
|
||||
fn Print(x: i32) = "print.int";
|
||||
fn PrintChar(x: i32) -> i32 = "print.char";
|
||||
fn ReadChar() -> i32 = "read.char";
|
||||
|
||||
// TODO: Change this to a global constant once they are fully supported.
|
||||
// TODO: Use simply -1 once we support negate on an IntLiteral.
|
||||
fn EOF() -> i32 { return -(1 as i32); }
|
||||
@@ -8,7 +8,3 @@ package Core library "prelude";
|
||||
|
||||
export import library "prelude/operators";
|
||||
export import library "prelude/types";
|
||||
|
||||
// TODO: Support printing other types.
|
||||
// TODO: Consider rewriting using native support once library support exists.
|
||||
fn Print(x: i32) = "print.int";
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# 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
|
||||
|
||||
load("//bazel/carbon_rules:defs.bzl", "carbon_binary")
|
||||
|
||||
utils = [
|
||||
"io_utils.carbon",
|
||||
"sort.carbon",
|
||||
]
|
||||
|
||||
carbon_binary(
|
||||
name = "day1_part1",
|
||||
srcs = [
|
||||
"day1_common.carbon",
|
||||
"day1_part1.carbon",
|
||||
] + utils,
|
||||
)
|
||||
|
||||
carbon_binary(
|
||||
name = "day1_part2",
|
||||
srcs = [
|
||||
"day1_common.carbon",
|
||||
"day1_part2.carbon",
|
||||
] + utils,
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
# Advent of Code 2024
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
This directory contains sample solutions written in Carbon for
|
||||
[Advent of Code 2024](https://adventofcode.com/2024/).
|
||||
|
||||
The Carbon toolchain is in a very early state, so these samples frequently need
|
||||
to work around missing functionality and are not reflective of expected Carbon
|
||||
style and idioms. Instead, the purpose of these examples are to test the current
|
||||
state of the toolchain against larger code examples than those that are present
|
||||
in the toolchain's own tests, to find bugs in the toolchain, and to drive
|
||||
feature development in the toolchain by presenting somewhat realistic testcases.
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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
|
||||
|
||||
library "day1_common";
|
||||
|
||||
import library "io_utils";
|
||||
|
||||
// Read a sequence of lines each containing a pair of numbers into two arrays.
|
||||
// Returns the number of lines read.
|
||||
fn ReadInputs(ap: [i32; 1000]*, bp: [i32; 1000]*) -> i32 {
|
||||
var n: i32 = 0;
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
while (n < 1000 and ReadInt(&a) and SkipSpaces() and ReadInt(&b) and SkipNewline()) {
|
||||
(*ap)[n] = a;
|
||||
(*bp)[n] = b;
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day1_common";
|
||||
import library "sort";
|
||||
|
||||
fn Abs(n: i32) -> i32 { return if n < 0 then -n else n; }
|
||||
|
||||
fn Run() {
|
||||
var a: [i32; 1000];
|
||||
var b: [i32; 1000];
|
||||
var n: i32 = ReadInputs(&a, &b);
|
||||
Quicksort(&a, 0, n);
|
||||
Quicksort(&b, 0, n);
|
||||
|
||||
var i: i32 = 0;
|
||||
var difference: i32 = 0;
|
||||
while (i < n) {
|
||||
difference += Abs(a[i] - b[i]);
|
||||
i += 1;
|
||||
}
|
||||
Core.Print(difference);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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
|
||||
|
||||
import Core library "io";
|
||||
|
||||
import library "day1_common";
|
||||
import library "sort";
|
||||
|
||||
fn Run() {
|
||||
var a: [i32; 1000];
|
||||
var b: [i32; 1000];
|
||||
var n: i32 = ReadInputs(&a, &b);
|
||||
Quicksort(&a, 0, n);
|
||||
Quicksort(&b, 0, n);
|
||||
|
||||
var i: i32 = 0;
|
||||
var j: i32 = 0;
|
||||
var similarity: i32 = 0;
|
||||
while (i < n and j < n) {
|
||||
if (a[i] < b[j]) {
|
||||
++i;
|
||||
} else {
|
||||
if (a[i] == b[j]) {
|
||||
similarity += b[j];
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
Core.Print(similarity);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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
|
||||
|
||||
library "io_utils";
|
||||
|
||||
import Core library "io";
|
||||
|
||||
// TODO: Use Core.EOF() rather than 0 as a sentinel here.
|
||||
// At the moment, 0 is the only value we can initialize a global to,
|
||||
// so we store the value plus 1 here.
|
||||
var push_back: i32 = 0;
|
||||
|
||||
fn ReadChar() -> i32 {
|
||||
var next: i32 = push_back - 1;
|
||||
push_back = 0;
|
||||
// TODO: assert(push_back == Core.EOF());
|
||||
if (next == Core.EOF()) {
|
||||
next = Core.ReadChar();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
fn UnreadChar(c: i32) {
|
||||
// TODO: assert(push_back == Core.EOF());
|
||||
push_back = c + 1;
|
||||
}
|
||||
|
||||
fn ReadInt(p: i32*) -> bool {
|
||||
var read_any_digits: bool = false;
|
||||
*p = 0;
|
||||
|
||||
while (true) {
|
||||
var c: i32 = ReadChar();
|
||||
if (c < 0x30 or c > 0x39) {
|
||||
UnreadChar(c);
|
||||
break;
|
||||
}
|
||||
// TODO: Check for overflow.
|
||||
*p *= 10;
|
||||
*p += c - 0x30;
|
||||
read_any_digits = true;
|
||||
}
|
||||
return read_any_digits;
|
||||
}
|
||||
|
||||
fn SkipSpaces() -> bool {
|
||||
var skipped_any_spaces: bool = false;
|
||||
while (true) {
|
||||
var c: i32 = ReadChar();
|
||||
if (c != 0x20) {
|
||||
UnreadChar(c);
|
||||
break;
|
||||
}
|
||||
skipped_any_spaces = true;
|
||||
}
|
||||
return skipped_any_spaces;
|
||||
}
|
||||
|
||||
fn SkipNewline() -> bool {
|
||||
var c: i32 = ReadChar();
|
||||
// Optional carriage return.
|
||||
if (c == 0x0D) {
|
||||
c = ReadChar();
|
||||
}
|
||||
// Newline.
|
||||
if (c == 0x0A) {
|
||||
return true;
|
||||
}
|
||||
// TODO: Unread the CR?
|
||||
UnreadChar(c);
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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
|
||||
|
||||
library "sort";
|
||||
|
||||
// TODO: Generalize this for other container types once we implement lowering
|
||||
// for generic functions.
|
||||
|
||||
fn Swap(p: [i32; 1000]*, from: i32, to: i32) {
|
||||
var tmp: i32 = (*p)[from];
|
||||
(*p)[from] = (*p)[to];
|
||||
(*p)[to] = tmp;
|
||||
}
|
||||
|
||||
fn Partition(p: [i32; 1000]*, from_in: i32, to_in: i32) -> i32 {
|
||||
var pivot_index: i32 = from_in;
|
||||
var pivot: i32 = (*p)[pivot_index];
|
||||
var from: i32 = from_in + 1;
|
||||
var to: i32 = to_in;
|
||||
while (from < to) {
|
||||
if ((*p)[from] <= pivot) {
|
||||
++from;
|
||||
} else if ((*p)[to - 1] > pivot) {
|
||||
--to;
|
||||
} else {
|
||||
// Element at `from` is > pivot, and
|
||||
// element at `to` is <= pivot.
|
||||
Swap(p, from, to - 1);
|
||||
++from;
|
||||
--to;
|
||||
}
|
||||
}
|
||||
Swap(p, pivot_index, from - 1);
|
||||
return from - 1;
|
||||
}
|
||||
|
||||
fn Quicksort(p: [i32; 1000]*, from: i32, to: i32) {
|
||||
if (from + 1 >= to) { return; }
|
||||
var pivot: i32 = Partition(p, from, to);
|
||||
Quicksort(p, from, pivot);
|
||||
Quicksort(p, pivot + 1, to);
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
import Core library "io";
|
||||
|
||||
// Compute and return the number of primes less than 1000.
|
||||
|
||||
class Sieve {
|
||||
|
||||
@@ -1107,8 +1107,11 @@ static auto MakeConstantForBuiltinCall(Context& context, SemIRLoc loc,
|
||||
case SemIR::BuiltinFunctionKind::None:
|
||||
CARBON_FATAL("Not a builtin function.");
|
||||
|
||||
case SemIR::BuiltinFunctionKind::PrintInt: {
|
||||
// Providing a constant result would allow eliding the function call.
|
||||
case SemIR::BuiltinFunctionKind::PrintChar:
|
||||
case SemIR::BuiltinFunctionKind::PrintInt:
|
||||
case SemIR::BuiltinFunctionKind::ReadChar: {
|
||||
// These are runtime-only builtins.
|
||||
// TODO: Consider tracking this on the `BuiltinFunctionKind`.
|
||||
return SemIR::ConstantId::NotConstant;
|
||||
}
|
||||
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// 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
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/print/char.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/print/char.carbon
|
||||
|
||||
import Core library "io";
|
||||
|
||||
fn PrintChar(a: i32) -> i32 = "print.char";
|
||||
|
||||
fn Main() {
|
||||
PrintChar(1);
|
||||
Core.PrintChar(2);
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- char.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [template]
|
||||
// CHECK:STDOUT: %PrintChar.type.1: type = fn_type @PrintChar.1 [template]
|
||||
// CHECK:STDOUT: %PrintChar.1: %PrintChar.type.1 = struct_value () [template]
|
||||
// CHECK:STDOUT: %Main.type: type = fn_type @Main [template]
|
||||
// CHECK:STDOUT: %Main: %Main.type = struct_value () [template]
|
||||
// CHECK:STDOUT: %int_1.1: Core.IntLiteral = int_value 1 [template]
|
||||
// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
|
||||
// CHECK:STDOUT: %Convert.type.10: type = fn_type @Convert.2, @impl.1(%int_32) [template]
|
||||
// CHECK:STDOUT: %Convert.10: %Convert.type.10 = struct_value () [template]
|
||||
// CHECK:STDOUT: %interface.5: <witness> = interface_witness (%Convert.10) [template]
|
||||
// CHECK:STDOUT: %Convert.bound.1: <bound method> = bound_method %int_1.1, %Convert.10 [template]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.1: <specific function> = specific_function %Convert.bound.1, @Convert.2(%int_32) [template]
|
||||
// CHECK:STDOUT: %int_1.2: %i32 = int_value 1 [template]
|
||||
// CHECK:STDOUT: %PrintChar.type.2: type = fn_type @PrintChar.2 [template]
|
||||
// CHECK:STDOUT: %PrintChar.2: %PrintChar.type.2 = struct_value () [template]
|
||||
// CHECK:STDOUT: %int_2.1: Core.IntLiteral = int_value 2 [template]
|
||||
// CHECK:STDOUT: %Convert.bound.2: <bound method> = bound_method %int_2.1, %Convert.10 [template]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.2: <specific function> = specific_function %Convert.bound.2, @Convert.2(%int_32) [template]
|
||||
// CHECK:STDOUT: %int_2.2: %i32 = int_value 2 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
|
||||
// CHECK:STDOUT: .Int = %import_ref.1
|
||||
// CHECK:STDOUT: .ImplicitAs = %import_ref.5
|
||||
// CHECK:STDOUT: .PrintChar = %import_ref.193
|
||||
// CHECK:STDOUT: import Core//prelude
|
||||
// CHECK:STDOUT: import Core//io
|
||||
// CHECK:STDOUT: import Core//prelude/...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.193: %PrintChar.type.2 = import_ref Core//io, PrintChar, loaded [template = constants.%PrintChar.2]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = imports.%Core
|
||||
// CHECK:STDOUT: .PrintChar = %PrintChar.decl
|
||||
// CHECK:STDOUT: .Main = %Main.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.import = import Core
|
||||
// CHECK:STDOUT: %PrintChar.decl: %PrintChar.type.1 = fn_decl @PrintChar.1 [template = constants.%PrintChar.1] {
|
||||
// CHECK:STDOUT: %a.patt: %i32 = binding_pattern a
|
||||
// CHECK:STDOUT: %a.param_patt: %i32 = value_param_pattern %a.patt, runtime_param0
|
||||
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
||||
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param1
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %int_32.loc13_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
|
||||
// CHECK:STDOUT: %i32.loc13_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
|
||||
// CHECK:STDOUT: %int_32.loc13_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
|
||||
// CHECK:STDOUT: %i32.loc13_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
|
||||
// CHECK:STDOUT: %a.param: %i32 = value_param runtime_param0
|
||||
// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param
|
||||
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param1
|
||||
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Main.decl: %Main.type = fn_decl @Main [template = constants.%Main] {} {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @PrintChar.1(%a.param_patt: %i32) -> %i32 = "print.char";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Main() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %PrintChar.ref.loc16: %PrintChar.type.1 = name_ref PrintChar, file.%PrintChar.decl [template = constants.%PrintChar.1]
|
||||
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.1]
|
||||
// CHECK:STDOUT: %impl.elem0.loc16: %Convert.type.2 = interface_witness_access constants.%interface.5, element0 [template = constants.%Convert.10]
|
||||
// CHECK:STDOUT: %Convert.bound.loc16: <bound method> = bound_method %int_1, %impl.elem0.loc16 [template = constants.%Convert.bound.1]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.loc16: <specific function> = specific_function %Convert.bound.loc16, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.1]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc16: init %i32 = call %Convert.specific_fn.loc16(%int_1) [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %.loc16_13.1: %i32 = value_of_initializer %int.convert_checked.loc16 [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %.loc16_13.2: %i32 = converted %int_1, %.loc16_13.1 [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %print.char.loc16: init %i32 = call %PrintChar.ref.loc16(%.loc16_13.2)
|
||||
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
|
||||
// CHECK:STDOUT: %PrintChar.ref.loc17: %PrintChar.type.2 = name_ref PrintChar, imports.%import_ref.193 [template = constants.%PrintChar.2]
|
||||
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.1]
|
||||
// CHECK:STDOUT: %impl.elem0.loc17: %Convert.type.2 = interface_witness_access constants.%interface.5, element0 [template = constants.%Convert.10]
|
||||
// CHECK:STDOUT: %Convert.bound.loc17: <bound method> = bound_method %int_2, %impl.elem0.loc17 [template = constants.%Convert.bound.2]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.loc17: <specific function> = specific_function %Convert.bound.loc17, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc17: init %i32 = call %Convert.specific_fn.loc17(%int_2) [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %.loc17_18.1: %i32 = value_of_initializer %int.convert_checked.loc17 [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %.loc17_18.2: %i32 = converted %int_2, %.loc17_18.1 [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %print.char.loc17: init %i32 = call %PrintChar.ref.loc17(%.loc17_18.2)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
Vendored
+24
-21
@@ -4,9 +4,11 @@
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/print.carbon
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/print/int.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/print.carbon
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/print/int.carbon
|
||||
|
||||
import Core library "io";
|
||||
|
||||
fn Print(a: i32) = "print.int";
|
||||
|
||||
@@ -16,7 +18,7 @@ fn Main() {
|
||||
Core.Print(2);
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- print.carbon
|
||||
// CHECK:STDOUT: --- int.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template]
|
||||
@@ -48,9 +50,10 @@ fn Main() {
|
||||
// CHECK:STDOUT: .ImplicitAs = %import_ref.5
|
||||
// CHECK:STDOUT: .Print = %import_ref.193
|
||||
// CHECK:STDOUT: import Core//prelude
|
||||
// CHECK:STDOUT: import Core//io
|
||||
// CHECK:STDOUT: import Core//prelude/...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.193: %Print.type.2 = import_ref Core//prelude, Print, loaded [template = constants.%Print.2]
|
||||
// CHECK:STDOUT: %import_ref.193: %Print.type.2 = import_ref Core//io, Print, loaded [template = constants.%Print.2]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -76,25 +79,25 @@ fn Main() {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Main() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Print.ref.loc14: %Print.type.1 = name_ref Print, file.%Print.decl [template = constants.%Print.1]
|
||||
// CHECK:STDOUT: %Print.ref.loc16: %Print.type.1 = name_ref Print, file.%Print.decl [template = constants.%Print.1]
|
||||
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.1]
|
||||
// CHECK:STDOUT: %impl.elem0.loc14: %Convert.type.2 = interface_witness_access constants.%interface.5, element0 [template = constants.%Convert.10]
|
||||
// CHECK:STDOUT: %Convert.bound.loc14: <bound method> = bound_method %int_1, %impl.elem0.loc14 [template = constants.%Convert.bound.1]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.loc14: <specific function> = specific_function %Convert.bound.loc14, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.1]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc14: init %i32 = call %Convert.specific_fn.loc14(%int_1) [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %.loc14_9.1: %i32 = value_of_initializer %int.convert_checked.loc14 [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %.loc14_9.2: %i32 = converted %int_1, %.loc14_9.1 [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %print.int.loc14: init %empty_tuple.type = call %Print.ref.loc14(%.loc14_9.2)
|
||||
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
|
||||
// CHECK:STDOUT: %Print.ref.loc16: %Print.type.2 = name_ref Print, imports.%import_ref.193 [template = constants.%Print.2]
|
||||
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.1]
|
||||
// CHECK:STDOUT: %impl.elem0.loc16: %Convert.type.2 = interface_witness_access constants.%interface.5, element0 [template = constants.%Convert.10]
|
||||
// CHECK:STDOUT: %Convert.bound.loc16: <bound method> = bound_method %int_2, %impl.elem0.loc16 [template = constants.%Convert.bound.2]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.loc16: <specific function> = specific_function %Convert.bound.loc16, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc16: init %i32 = call %Convert.specific_fn.loc16(%int_2) [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %.loc16_14.1: %i32 = value_of_initializer %int.convert_checked.loc16 [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %.loc16_14.2: %i32 = converted %int_2, %.loc16_14.1 [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %print.int.loc16: init %empty_tuple.type = call %Print.ref.loc16(%.loc16_14.2)
|
||||
// CHECK:STDOUT: %Convert.bound.loc16: <bound method> = bound_method %int_1, %impl.elem0.loc16 [template = constants.%Convert.bound.1]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.loc16: <specific function> = specific_function %Convert.bound.loc16, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.1]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc16: init %i32 = call %Convert.specific_fn.loc16(%int_1) [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %.loc16_9.1: %i32 = value_of_initializer %int.convert_checked.loc16 [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %.loc16_9.2: %i32 = converted %int_1, %.loc16_9.1 [template = constants.%int_1.2]
|
||||
// CHECK:STDOUT: %print.int.loc16: init %empty_tuple.type = call %Print.ref.loc16(%.loc16_9.2)
|
||||
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
|
||||
// CHECK:STDOUT: %Print.ref.loc18: %Print.type.2 = name_ref Print, imports.%import_ref.193 [template = constants.%Print.2]
|
||||
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.1]
|
||||
// CHECK:STDOUT: %impl.elem0.loc18: %Convert.type.2 = interface_witness_access constants.%interface.5, element0 [template = constants.%Convert.10]
|
||||
// CHECK:STDOUT: %Convert.bound.loc18: <bound method> = bound_method %int_2, %impl.elem0.loc18 [template = constants.%Convert.bound.2]
|
||||
// CHECK:STDOUT: %Convert.specific_fn.loc18: <specific function> = specific_function %Convert.bound.loc18, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc18: init %i32 = call %Convert.specific_fn.loc18(%int_2) [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %.loc18_14.1: %i32 = value_of_initializer %int.convert_checked.loc18 [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %.loc18_14.2: %i32 = converted %int_2, %.loc18_14.1 [template = constants.%int_2.2]
|
||||
// CHECK:STDOUT: %print.int.loc18: init %empty_tuple.type = call %Print.ref.loc18(%.loc18_14.2)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,84 @@
|
||||
// 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
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/read/int.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/read/int.carbon
|
||||
|
||||
import Core library "io";
|
||||
|
||||
fn ReadChar() -> i32 = "read.char";
|
||||
|
||||
fn Main() {
|
||||
let n: i32 = ReadChar();
|
||||
let m: i32 = Core.ReadChar();
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- int.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [template]
|
||||
// CHECK:STDOUT: %ReadChar.type.1: type = fn_type @ReadChar.1 [template]
|
||||
// CHECK:STDOUT: %ReadChar.1: %ReadChar.type.1 = struct_value () [template]
|
||||
// CHECK:STDOUT: %Main.type: type = fn_type @Main [template]
|
||||
// CHECK:STDOUT: %Main: %Main.type = struct_value () [template]
|
||||
// CHECK:STDOUT: %ReadChar.type.2: type = fn_type @ReadChar.2 [template]
|
||||
// CHECK:STDOUT: %ReadChar.2: %ReadChar.type.2 = struct_value () [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
|
||||
// CHECK:STDOUT: .Int = %import_ref.1
|
||||
// CHECK:STDOUT: .ReadChar = %import_ref.5
|
||||
// CHECK:STDOUT: import Core//prelude
|
||||
// CHECK:STDOUT: import Core//io
|
||||
// CHECK:STDOUT: import Core//prelude/...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %import_ref.5: %ReadChar.type.2 = import_ref Core//io, ReadChar, loaded [template = constants.%ReadChar.2]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = imports.%Core
|
||||
// CHECK:STDOUT: .ReadChar = %ReadChar.decl
|
||||
// CHECK:STDOUT: .Main = %Main.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core.import = import Core
|
||||
// CHECK:STDOUT: %ReadChar.decl: %ReadChar.type.1 = fn_decl @ReadChar.1 [template = constants.%ReadChar.1] {
|
||||
// CHECK:STDOUT: %return.patt: %i32 = return_slot_pattern
|
||||
// CHECK:STDOUT: %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param0
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
|
||||
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param0
|
||||
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Main.decl: %Main.type = fn_decl @Main [template = constants.%Main] {} {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @ReadChar.1() -> %i32 = "read.char";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Main() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %int_32.loc16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
|
||||
// CHECK:STDOUT: %i32.loc16: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
|
||||
// CHECK:STDOUT: %ReadChar.ref.loc16: %ReadChar.type.1 = name_ref ReadChar, file.%ReadChar.decl [template = constants.%ReadChar.1]
|
||||
// CHECK:STDOUT: %read.char.loc16: init %i32 = call %ReadChar.ref.loc16()
|
||||
// CHECK:STDOUT: %.loc16_26.1: %i32 = value_of_initializer %read.char.loc16
|
||||
// CHECK:STDOUT: %.loc16_26.2: %i32 = converted %read.char.loc16, %.loc16_26.1
|
||||
// CHECK:STDOUT: %n: %i32 = bind_name n, %.loc16_26.2
|
||||
// CHECK:STDOUT: %int_32.loc17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
|
||||
// CHECK:STDOUT: %i32.loc17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
|
||||
// CHECK:STDOUT: %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
|
||||
// CHECK:STDOUT: %ReadChar.ref.loc17: %ReadChar.type.2 = name_ref ReadChar, imports.%import_ref.5 [template = constants.%ReadChar.2]
|
||||
// CHECK:STDOUT: %read.char.loc17: init %i32 = call %ReadChar.ref.loc17()
|
||||
// CHECK:STDOUT: %.loc17_31.1: %i32 = value_of_initializer %read.char.loc17
|
||||
// CHECK:STDOUT: %.loc17_31.2: %i32 = converted %read.char.loc17, %.loc17_31.1
|
||||
// CHECK:STDOUT: %m: %i32 = bind_name m, %.loc17_31.2
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -76,20 +76,48 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id,
|
||||
case SemIR::BuiltinFunctionKind::None:
|
||||
CARBON_FATAL("No callee in function call.");
|
||||
|
||||
case SemIR::BuiltinFunctionKind::PrintChar: {
|
||||
auto* i32_type = llvm::IntegerType::getInt32Ty(context.llvm_context());
|
||||
llvm::Value* arg_value = context.builder().CreateSExtOrTrunc(
|
||||
context.GetValue(arg_ids[0]), i32_type);
|
||||
auto putchar = context.llvm_module().getOrInsertFunction(
|
||||
"putchar", i32_type, i32_type);
|
||||
auto* result = context.builder().CreateCall(putchar, {arg_value});
|
||||
context.SetLocal(
|
||||
inst_id,
|
||||
context.builder().CreateSExtOrTrunc(
|
||||
result, context.GetType(
|
||||
context.sem_ir().insts().Get(inst_id).type_id())));
|
||||
return;
|
||||
}
|
||||
|
||||
case SemIR::BuiltinFunctionKind::PrintInt: {
|
||||
llvm::Type* char_type[] = {llvm::PointerType::get(
|
||||
llvm::Type::getInt8Ty(context.llvm_context()), 0)};
|
||||
auto* printf_type = llvm::FunctionType::get(
|
||||
llvm::IntegerType::getInt32Ty(context.llvm_context()),
|
||||
llvm::ArrayRef<llvm::Type*>(char_type, 1), /*isVarArg=*/true);
|
||||
auto callee =
|
||||
auto* i32_type = llvm::IntegerType::getInt32Ty(context.llvm_context());
|
||||
auto* ptr_type = llvm::PointerType::get(context.llvm_context(), 0);
|
||||
auto* printf_type = llvm::FunctionType::get(i32_type, {ptr_type},
|
||||
/*isVarArg=*/true);
|
||||
llvm::FunctionCallee printf =
|
||||
context.llvm_module().getOrInsertFunction("printf", printf_type);
|
||||
|
||||
llvm::SmallVector<llvm::Value*, 1> args = {
|
||||
context.builder().CreateGlobalString("%d\n", "printf.int.format")};
|
||||
args.push_back(context.GetValue(arg_ids[0]));
|
||||
context.SetLocal(inst_id,
|
||||
context.builder().CreateCall(callee, args, "printf"));
|
||||
llvm::Value* format_string =
|
||||
context.builder().CreateGlobalString("%d\n", "printf.int.format");
|
||||
llvm::Value* arg_value = context.builder().CreateSExtOrTrunc(
|
||||
context.GetValue(arg_ids[0]), i32_type);
|
||||
context.SetLocal(inst_id, context.builder().CreateCall(
|
||||
printf, {format_string, arg_value}));
|
||||
return;
|
||||
}
|
||||
|
||||
case SemIR::BuiltinFunctionKind::ReadChar: {
|
||||
auto* i32_type = llvm::IntegerType::getInt32Ty(context.llvm_context());
|
||||
auto getchar =
|
||||
context.llvm_module().getOrInsertFunction("getchar", i32_type);
|
||||
auto* result = context.builder().CreateCall(getchar, {});
|
||||
context.SetLocal(
|
||||
inst_id,
|
||||
context.builder().CreateSExtOrTrunc(
|
||||
result, context.GetType(
|
||||
context.sem_ir().insts().Get(inst_id).type_id())));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
-39
@@ -1,39 +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
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/builtins/print.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/builtins/print.carbon
|
||||
|
||||
fn Main() {
|
||||
Core.Print(1);
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: ; ModuleID = 'print.carbon'
|
||||
// CHECK:STDOUT: source_filename = "print.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: @printf.int.format = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define void @_CMain.Main() !dbg !4 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %print.int.printf = call i32 (ptr, ...) @printf(ptr @printf.int.format, i32 1), !dbg !7
|
||||
// CHECK:STDOUT: ret void, !dbg !8
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare i32 @printf(ptr, ...)
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
|
||||
// CHECK:STDOUT: !llvm.dbg.cu = !{!2}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
||||
// CHECK:STDOUT: !3 = !DIFile(filename: "print.carbon", directory: "")
|
||||
// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "Main", linkageName: "_CMain.Main", scope: null, file: !3, line: 11, type: !5, spFlags: DISPFlagDefinition, unit: !2)
|
||||
// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
|
||||
// CHECK:STDOUT: !6 = !{}
|
||||
// CHECK:STDOUT: !7 = !DILocation(line: 12, column: 3, scope: !4)
|
||||
// CHECK:STDOUT: !8 = !DILocation(line: 11, column: 1, scope: !4)
|
||||
@@ -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
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/builtins/print_read.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/builtins/print_read.carbon
|
||||
|
||||
import Core library "io";
|
||||
|
||||
fn PrintChar(c: i8) -> i32 = "print.char";
|
||||
fn ReadChar() -> i32 = "read.char";
|
||||
|
||||
fn Main() {
|
||||
Core.Print(1);
|
||||
|
||||
let EOF: i32 = -(1 as i32);
|
||||
while (ReadChar() != EOF) {
|
||||
// "Hi"
|
||||
if (PrintChar(0x48) != EOF) {
|
||||
PrintChar(0x69);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: ; ModuleID = 'print_read.carbon'
|
||||
// CHECK:STDOUT: source_filename = "print_read.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: @printf.int.format = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define void @_CMain.Main() !dbg !4 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %print.int = call i32 (ptr, ...) @printf(ptr @printf.int.format, i32 1), !dbg !7
|
||||
// CHECK:STDOUT: br label %while.cond, !dbg !8
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: while.cond: ; preds = %if.else, %entry
|
||||
// CHECK:STDOUT: %read.char = call i32 @getchar(), !dbg !9
|
||||
// CHECK:STDOUT: %int.neq.loc20 = icmp ne i32 %read.char, -1, !dbg !9
|
||||
// CHECK:STDOUT: br i1 %int.neq.loc20, label %while.body, label %while.done, !dbg !8
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: while.body: ; preds = %while.cond
|
||||
// CHECK:STDOUT: %print.char.loc22 = call i32 @putchar(i32 72), !dbg !10
|
||||
// CHECK:STDOUT: %int.neq.loc22 = icmp ne i32 %print.char.loc22, -1, !dbg !10
|
||||
// CHECK:STDOUT: br i1 %int.neq.loc22, label %if.then, label %if.else, !dbg !11
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: if.then: ; preds = %while.body
|
||||
// CHECK:STDOUT: %print.char.loc23 = call i32 @putchar(i32 105), !dbg !12
|
||||
// CHECK:STDOUT: br label %if.else, !dbg !13
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: if.else: ; preds = %if.then, %while.body
|
||||
// CHECK:STDOUT: br label %while.cond, !dbg !14
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: while.done: ; preds = %while.cond
|
||||
// CHECK:STDOUT: ret void, !dbg !15
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare i32 @printf(ptr, ...)
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare i32 @getchar()
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare i32 @putchar(i32)
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @putchar, { 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
|
||||
// CHECK:STDOUT: !llvm.dbg.cu = !{!2}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
||||
// CHECK:STDOUT: !3 = !DIFile(filename: "print_read.carbon", directory: "")
|
||||
// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "Main", linkageName: "_CMain.Main", scope: null, file: !3, line: 16, type: !5, spFlags: DISPFlagDefinition, unit: !2)
|
||||
// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
|
||||
// CHECK:STDOUT: !6 = !{}
|
||||
// CHECK:STDOUT: !7 = !DILocation(line: 17, column: 3, scope: !4)
|
||||
// CHECK:STDOUT: !8 = !DILocation(line: 20, column: 9, scope: !4)
|
||||
// CHECK:STDOUT: !9 = !DILocation(line: 20, column: 10, scope: !4)
|
||||
// CHECK:STDOUT: !10 = !DILocation(line: 22, column: 9, scope: !4)
|
||||
// CHECK:STDOUT: !11 = !DILocation(line: 22, column: 8, scope: !4)
|
||||
// CHECK:STDOUT: !12 = !DILocation(line: 23, column: 7, scope: !4)
|
||||
// CHECK:STDOUT: !13 = !DILocation(line: 22, column: 5, scope: !4)
|
||||
// CHECK:STDOUT: !14 = !DILocation(line: 20, column: 3, scope: !4)
|
||||
// CHECK:STDOUT: !15 = !DILocation(line: 16, column: 1, scope: !4)
|
||||
@@ -63,7 +63,8 @@ struct BuiltinType {
|
||||
}
|
||||
};
|
||||
|
||||
// Constraint that the function has no return.
|
||||
// Constraint that a type is `()`, used as the return type of builtin functions
|
||||
// with no return value.
|
||||
struct NoReturn {
|
||||
static auto Check(const File& sem_ir, ValidateState& /*state*/,
|
||||
TypeId type_id) -> bool {
|
||||
@@ -194,10 +195,18 @@ using FloatT = TypeParam<0, AnyFloat>;
|
||||
// Not a builtin function.
|
||||
constexpr BuiltinInfo None = {"", nullptr};
|
||||
|
||||
// Prints an argument.
|
||||
// Prints a single character.
|
||||
constexpr BuiltinInfo PrintChar = {"print.char",
|
||||
ValidateSignature<auto(AnyInt)->AnyInt>};
|
||||
|
||||
// Prints an integer.
|
||||
constexpr BuiltinInfo PrintInt = {"print.int",
|
||||
ValidateSignature<auto(AnyInt)->NoReturn>};
|
||||
|
||||
// Reads a single character from stdin.
|
||||
constexpr BuiltinInfo ReadChar = {"read.char",
|
||||
ValidateSignature<auto()->AnyInt>};
|
||||
|
||||
// Returns the `Core.IntLiteral` type.
|
||||
constexpr BuiltinInfo IntLiteralMakeType = {"int_literal.make_type",
|
||||
ValidateSignature<auto()->Type>};
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
#endif
|
||||
|
||||
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(None)
|
||||
|
||||
// Temporary builtins for primitive IO.
|
||||
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(PrintChar)
|
||||
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(PrintInt)
|
||||
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(ReadChar)
|
||||
|
||||
// Type factories.
|
||||
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntLiteralMakeType)
|
||||
|
||||
Reference in New Issue
Block a user