명령줄의 `gh`로 GitHub 이슈 본문과 댓글을 읽기 전용으로 확인하는 방법을 안내합니다. 번호나 URL로 이슈를 찾고 다른 저장소를 지정하는 방법, 댓글이 많은 경우 JSON과 `jq`로 내용을 추출하는 방법을 다룹니다.
- 이슈 본문과 댓글 읽기
- URL로 이슈 내용 확인
- 다른 저장소의 이슈 조회
Carbon 컴파일러에 내장 함수를 추가하는 절차를 안내합니다. 함수 등록과 시그니처 검증부터 상수 평가, 런타임 호출의 LLVM IR 생성, Prelude 연결, 최소 Prelude를 이용한 개별 테스트까지 다룹니다.
Instructions for registering, mapping, constant evaluating, and lowering builtin functions in the Carbon toolchain.
실행 점수 미검증
설치 방법 보기이 스킬은 Carbon 컴파일러에 내장 함수를 추가하는 절차를 설명합니다. 함수 종류 등록, 이름과 매개변수 제약의 연결, 컴파일 시에만 실행되는 함수의 지정, 상수 평가 구현, 런타임 호출을 LLVM IR로 낮추기, Prelude에 바인딩 추가하기를 다룹니다. 정수와 부동 소수점 값을 처리할 때의 범위 검사와 진단, 최소 Prelude를 사용해 내장 함수를 개별적으로 검증하는 테스트 작성 방법도 안내합니다.
Carbon 내장 함수를 새로 만들거나 수정할 때 활용할 수 있습니다. 컴파일 시 평가와 런타임 코드 생성을 각각 어디에 구현할지 정리하거나, Prelude 연결과 분리된 테스트 방법을 확인할 때 유용합니다.
C++, LLVM IR, Carbon 컴파일러 구조에 대한 이해를 전제로 합니다.
이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.
AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.
점수에는 넣지 않았습니다. 2026년 10월 26일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
Builtin functions are compiler-recognized primitives mapping directly from Carbon code expressions (via standard prelude bindings) to optimized backend execution. This document defines the complete structural workflow, C++ patterns, constant evaluation logic, machine lowering mechanics, library bindings, and validation strategies required to implement builtin functions in the Carbon compiler.
graph TD
Src[Carbon Source Code] -->|Prelude Map| Sem[Semantic Analysis / SemIR]
Sem -->|Signature Constraint| Sig[builtin_function_kind.cpp]
Sem -->|Phase Evaluation| Eval[eval.cpp Constant Interpreter]
Sem -->|Machine Codegen| Lower[handle_call.cpp LLVM Lowering]
Eval -->|Diagnostics| Diag[diagnostics/kind.def]
Lower -->|Native Instructions| LLVM[LLVM IR Generation]
Adding a builtin function involves a 5-step integration:
Register your builtin function name using the X-macro in builtin_function_kind.def:
// toolchain/sem_ir/builtin_function_kind.def
// Converts an integer type to a floating-point type.
CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertFloat)
Inside builtin_function_kind.cpp:
Define Parameter Constraints: If the parameter requires novel
constraints (e.g. "must be a float type"), define a template constraint
struct checking the matching SemIR type instruction (such as FloatType
or FloatLiteralType). Use pre-established semantic helpers:
TypeParam<I, T>: Ensures different parameters resolve to identical
type structures (e.g., generic constraint matching).AnyInt, AnyFloat, AnySizedInt, AnySizedFloat, CharCompatible,
StdInitializerList, NoReturn.Map Literal Name & Register Constraint Signature: Declare a
BuiltinInfo constant inside namespace BuiltinFunctionInfo matching the
macro-defined name:
// toolchain/sem_ir/builtin_function_kind.cpp
constexpr BuiltinInfo IntConvertFloat = {
"int.convert_float", ValidateSignature<auto(AnyInt)->AnyFloat>};
Establish Compile-Time Residency Status: Update
BuiltinFunctionKind::IsCompTimeOnly to determine if a call requires
compile-time evaluation:
true immediately. Runtime
lowering of these is illegal (e.g. IntConvertFloatChecked).AnyLiteralTypes(sem_ir, arg_ids, return_type_id) to enforce that
expressions involving unsized literal values (like IntLiteral or
FloatLiteral) are evaluated exclusively at compile-time (as they lack
runtime representation).Wire the interpreter inside eval.cpp to execute compile-time computations:
Implement Constant Evaluation Logic:
Handle the builtin case inside MakeConstantForBuiltinCall (which
processes the compile-time execution of the call).
Confirm type validation phase is Phase::Concrete to reject incomplete
bindings:
case SemIR::BuiltinFunctionKind::IntConvertFloat: {
if (phase != Phase::Concrete) {
return MakeConstantResult(context, call, phase);
}
return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,
/*require_exact=*/false);
}
Extract inputs safely from local value stores (e.g.
context.ints().Get(arg.int_id) or
context.floats().Get(arg.float_id)).
Leverage high-precision LLVM mathematical structures (llvm::APInt,
llvm::APFloat, llvm::APSInt) to handle custom bits and signedness
safely.
Diagnose Invalid Parameters or Exceptions:
Define compile-time diagnostics inside kind.def:
// toolchain/diagnostics/kind.def
CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)
Emplace localized diagnostic formatting messages where they are caught
in eval.cpp:
CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,
"integer value {0} too large for floating-point type {1}",
llvm::APSInt, SemIR::TypeId);
context.emitter().Emit(loc_id, IntTooLargeForFloatType, val, dest_type_id);
Return SemIR::ErrorInst::ConstantId to gracefully abort invalid
constant generation rather than crashing the compiler.
Fast-Path Range Limits:
1.0e1000000), executing range limits check against dest_width + 64
(sized) or IntStore::MaxIntWidth (unsized) is mandatory to prevent
out-of-bounds calculations and compile-time memory exhaustion.Inside handle_call.cpp:
Map to Native LLVM Instructions: For runtime-eligible builtins, map the
call inside HandleBuiltinCall to native LLVM IR builder methods:
case SemIR::BuiltinFunctionKind::IntConvertFloat: {
auto* operand = context.GetValue(arg_ids[0]);
auto* dest_type = context.GetTypeOfInst(inst_id);
bool is_signed = IsSignedInt(context, arg_ids[0]);
context.SetLocal(
inst_id, is_signed
? context.builder().CreateSIToFP(operand, dest_type)
: context.builder().CreateUIToFP(operand, dest_type));
return;
}
Assert on Compile-Time-Only Builtins: Throw a hard assertion on lowering-cases for checked validator builtins that should never hit code generation:
case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {
CARBON_CHECK(builtin_kind.IsCompTimeOnly(
context.sem_ir(), arg_ids,
context.sem_ir().insts().Get(inst_id).type_id()));
CARBON_FATAL("Missing constant value for call to comptime-only function");
}
Map the standard library primitive interfaces to your newly minted named builtins under core/prelude/:
Primitive Mappings: Bind Carbon methods directly to string-literal builtin equivalents:
fn Convert[self: Self]() -> Float(To) = "int.convert_float";
Strict Orphan Rule Compliance: Carbon's orphan rules prohibit implementing interfaces where neither the type nor the interface is locally defined in the backing source module.
FloatLiteral,
IntLiteral) do not have backing Carbon source files. Therefore, an
impl of UnsafeAs (which is defined in as.carbon) between two
literal types must reside inside as.carbon itself.Int(N), Float(N)) must reside in their respective type source files
(such as int.carbon or
float.carbon) where the
backing target type resides to prevent duplicate symbols and structural
recursion loops.Follow the Toolchain tests skill with specialized patterns for builtins:
Create validation splits under toolchain/check/testdata/builtins/:
. characters
in the builtin name with / (directories). For example, a test for the
builtin "char_literal.convert" must be located at
toolchain/check/testdata/builtins/char_literal/convert.carbon.// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon) or a smaller
prelude, and explicitly declare and call the builtin functions under test
directly (e.g., fn Add(a: f64, b: f64) -> f64 = "float.add";). This
isolates the testing of compiler builtins from the library prelude.+, -, /, <,
etc.) are not available in minimized preludes because the core operators
library isn't imported. To write tests with a minimal footprint, call
primitive builtins directly (e.g. float.negate, float.div) inside your
test code to build expressions.RealId objects
based on spelling variations. Verify compile-time constant conversions using
canonicalized comparison functions (e.g. passing converted results through
Expect(X as f64)) to completely avoid spelling mismatches in expected
outputs.Create testing splits under toolchain/lower/testdata/builtins/:
sitofp i32 %a to float, fptosi float %a to i32).아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
명령줄의 `gh`로 GitHub 이슈 본문과 댓글을 읽기 전용으로 확인하는 방법을 안내합니다. 번호나 URL로 이슈를 찾고 다른 저장소를 지정하는 방법, 댓글이 많은 경우 JSON과 `jq`로 내용을 추출하는 방법을 다룹니다.
Carbon 저장소에서 일하는 AI 도우미가 전용 환경 도구로 파일을 읽고 검색하고 편집하는 규칙을 안내합니다. 임시 파일을 둘 위치와 삭제 시점, 사용자 지정 프로그램을 허용하는 경우도 설명합니다.
Carbon 프로젝트에서 Bazelisk로 빌드, 테스트, 실행하는 기본 절차를 안내합니다. 대상을 지정한 검증, ASan 활성화, 시스템 의존성 변경 후 캐시 재생성도 다룹니다.
Carbon 툴체인의 Bazel, C++, Carbon, Markdown, Python 파일 서식 기준을 안내합니다. 주석, 문서, 이름, 설계 원칙과 변경 내용을 설명하는 커밋 메시지 작성법도 다룹니다.
Carbon 도구 체인에서 오류와 경고 진단을 추가하거나 수정하는 방법을 안내합니다. 진단 종류 등록, 형식이 지정된 인수로 메시지 구성, 소스 위치에 라벨과 문맥 연결, 문구 규칙 및 테스트 범위 확인을 다룹니다.
`gh`로 GitHub 이슈, 풀 리퀘스트, 저장소와 코드를 읽기 전용으로 검색하고 확인하는 방법을 안내합니다. REST·GraphQL API 조회, 페이지별 결과 수집, 출력 필터링과 형식 지정도 다룹니다.