跳到正文
cccskills
免费在 GitHub 公开中文介绍

Builtin functions

本技能介绍如何为Carbon编译器添加内置函数,包括类型注册、签名验证、常量求值、运行时LLVM IR生成、Prelude绑定,以及使用最小Prelude编写针对性测试。

原文查看原文说明

Instructions for registering, mapping, constant evaluating, and lowering builtin functions in the Carbon toolchain.

carbon-language/carbon-lang星标 33,929(GitHub 33,929 + cccskills 0)

实测评分 未实测

查看安装方法

适用场景

  • 注册内置函数
  • 实现常量求值
  • 添加LLVM IR生成
  • 编写内置函数测试

中文介绍

功能

本技能说明为Carbon编译器添加内置函数的完整流程,包括注册函数种类、将名称与参数约束关联、指定函数是否仅在编译时运行、实现常量求值、将运行时调用降低为LLVM IR,以及在Prelude中添加绑定。内容还涉及整数和浮点数值的范围检查与诊断,并说明如何使用最小Prelude编写测试,单独验证内置函数。

适用场景

新建或修改Carbon内置函数时,可以参考本技能。它可帮助开发者确定编译时求值和运行时代码生成分别应实现在哪里,并了解如何连接Prelude以及如何隔离测试。

使用示例

  • “请说明如何注册内置函数并实现其常量求值。”
  • “这个内置函数应在哪里降低为LLVM IR?”
  • “请创建一个不依赖Prelude的内置函数测试。”

注意事项

本技能以熟悉C++、LLVM IR和Carbon编译器结构为前提。

本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。

文档检查

AI 根据 SKILL.md 的内容检查了需要注意的操作和使用前提。评分只依据实际运行的结果(实测对比)。

安全性发送数据、删除文件、执行命令等是否有说明
A良好资料涉及编译器实现和测试,未提及外发或删除操作。
安装难易度所需工具和 API 密钥是否少且有说明
B部分不足资料以C++、LLVM IR和Carbon编译器知识为前提,但未提供环境安装步骤。

不计入评分。 由 AI(OpenAI Codex)于 2026年10月26日 评估。仅供参考,安装前请同时查看原文。

如果您认为评估有误,请申请复核

请写明哪一项有误以及原因。无需登录。我们会对照 SKILL.md 重新评估,并在此处更新结果。

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

包含的文件(1)

  • SKILL.md11.3 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Builtin Functions in the Carbon Toolchain

<!-- 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 -->

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.


Technical Flow & Lifecycle

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:

  1. Define the Builtin Kind: Register the enum in builtin_function_kind.def.
  2. Signature & Compile-Time Registry: Declare the mapping name, parameter constraints, and compile-time evaluation residency in builtin_function_kind.cpp.
  3. Compile-Time Interpreter Support: Wire constant evaluation hooks and bounds/exception diagnostics in eval.cpp.
  4. LLVM IR Lowering Support: Connect target machine generation in handle_call.cpp.
  5. Prelude Library Mapping: Bind primitive interfaces to named builtins under core/prelude/.

Detailed Step-by-Step Implementation Guide

Step 1: Kind Definition & Registration

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)

Step 2: Signature Validation & Compile-Time Residence

Inside builtin_function_kind.cpp:

  1. 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.
  2. 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>};
    
  3. Establish Compile-Time Residency Status: Update BuiltinFunctionKind::IsCompTimeOnly to determine if a call requires compile-time evaluation:

    • Checked/Diagnostics Primitives: Return true immediately. Runtime lowering of these is illegal (e.g. IntConvertFloatChecked).
    • Runtime Primitives: Return 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).

Step 3: Constant Evaluation Support

Wire the interpreter inside eval.cpp to execute compile-time computations:

  1. 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.

  2. 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.

  3. Fast-Path Range Limits:

    • Before evaluating expensive math operations on giant exponents (e.g. 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.

Step 4: Machine Code Generation (LLVM Lowering)

Inside handle_call.cpp:

  1. 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;
    }
    
  2. 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");
    }
    

Step 5: Standard Library Prelude Integration

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.

    • Literal Conversions: Literal types (like 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.
    • Sized Conversions: Implementations targeting sized primitives (e.g. 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.

High-Fidelity Validation & Test Authoring

Follow the Toolchain tests skill with specialized patterns for builtins:

1. Checker Builtin File Splits

Create validation splits under toolchain/check/testdata/builtins/:

  • Test Naming Convention: All tests under toolchain/check/testdata/builtins/ must be named after the builtin they are testing, replacing . 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.
  • Minimal Prelude & Direct Call Isolation: Builtin tests must not test the prelude library or operators. They must use the minimal primitive prelude (// 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.
  • Min-Prelude Limitations: Standard operators (like +, -, /, <, 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.
  • Canonicalized Float Comparison: In SemIR, real literal representations with identical mathematical values can result in mismatched 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.
  • Locals Bypass: If validating generic implicit conversions, compile-time arguments cannot take local runtime variable parameters. Validate compile-time conversions by passing literal constants directly, and sized variable implicit conversions at runtime.

2. Machine Codegen Lowering Splits

Create testing splits under toolchain/lower/testdata/builtins/:

  • Emplace a simple carbon binding to the tested builtin.
  • Confirm matching LLVM metadata target definitions are mapped precisely (e.g., matching sitofp i32 %a to float, fptosi float %a to i32).

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

本技能介绍如何使用命令行`gh`只读查看GitHub issue正文和评论,支持通过编号或URL定位,也可指定其他仓库,并说明如何提取大量评论。

  • 查看issue正文和评论
  • 通过URL读取issue
  • 查看其他仓库的issue
carbon-language/carbon-lang3.4万2026年10月26日 更新

Agent tools

免费有简介

本技能为在 Carbon 代码库中工作的 AI 助手规定文件查看、搜索和编辑工具,并说明临时文件的存放与清理规则,以及何时可以编写和运行自定义程序。

  • 按规定工具搜索Carbon文件
  • 为文件编辑选择专用工具
  • 确认临时文件的存放与清理规则
carbon-language/carbon-lang3.4万2026年10月26日 更新

Bazel usage

免费有简介

了解如何在 Carbon 项目中通过 Bazelisk 构建、测试和运行程序,包括指定目标、启用 ASan,以及系统依赖变更后重建缓存。

  • 构建 Carbon 代码
  • 运行与修改相关的测试
  • 启动 Bazel 构建的程序
carbon-language/carbon-lang3.4万2026年10月26日 更新

Code style

免费有简介

了解 Carbon 工具链对 Bazel、C++、Carbon、Markdown 和 Python 文件的格式规范,并查看注释、文档、命名、设计及提交说明的写作要求。

  • 整理 Carbon 代码格式
  • 检查注释和文档
  • 确认名称是否符合实际含义
carbon-language/carbon-lang3.4万2026年10月26日 更新

Diagnostics

免费有简介

本技能介绍如何在Carbon工具链中添加或修改错误和警告,包括注册诊断类型、用带类型的参数构造消息、为源码位置添加标签和上下文,以及检查措辞规范和测试覆盖。

  • 添加诊断消息
  • 为源码位置添加标签
  • 统一诊断措辞
carbon-language/carbon-lang3.4万2026年10月26日 更新

GitHub CLI usage

免费有简介

使用 `gh` 只读搜索和查看 GitHub 的议题、拉取请求、仓库与代码,并了解如何查询 REST 和 GraphQL API、翻页获取结果及筛选或整理输出。

  • 查看议题内容和状态
  • 检查拉取请求差异与检查状态
  • 搜索 GitHub 代码或仓库
carbon-language/carbon-lang3.4万2026年10月26日 更新

查看 carbon-language 的全部技能

报告此技能的问题